Build a new Hass.io panel (#1271)

* Build a new Hass.io panel

* Use webcomponents-lite.js

* Compress new panel

* Lint
pull/1273/head
Paulus Schoutsen 2018-06-08 15:26:48 -04:00 committed by GitHub
parent 92930a2b94
commit d243f2ead6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 112 additions and 101 deletions

View File

@ -2,7 +2,9 @@ const path = require('path');
module.exports = { module.exports = {
// Target directory for the build. // Target directory for the build.
buildDir: path.resolve(__dirname, 'build-es5'), buildDirLegacy: path.resolve(__dirname, 'build-es5'),
buildDir: path.resolve(__dirname, 'build'),
// Path where the Hass.io frontend will be publicly available. // Path where the Hass.io frontend will be publicly available.
publicPath: '/api/hassio/app-es5' publicPath: '/api/hassio/app',
publicPathLegacy: '/api/hassio/app-es5',
} }

View File

@ -26,7 +26,7 @@
'import' in document.createElement('link') && 'import' in document.createElement('link') &&
'content' in document.createElement('template')); 'content' in document.createElement('template'));
if (!webComponentsSupported) { if (!webComponentsSupported) {
addScript('/static/webcomponents-bundle.js'); addScript('/static/webcomponents-lite.js');
} }
</script> </script>
<!-- <!--

View File

@ -6,11 +6,14 @@ set -e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
OUTPUT_DIR=build
OUTPUT_DIR_ES5=build-es5 OUTPUT_DIR_ES5=build-es5
rm -rf $OUTPUT_DIR_ES5 rm -rf $OUTPUT_DIR $OUTPUT_DIR_ES5
node script/gen-icons.js node script/gen-icons.js
NODE_ENV=production ../node_modules/.bin/webpack -p
# LEGACY BUILD
NODE_ENV=production ../node_modules/.bin/webpack -p --config webpack.legacy.config.js
node script/gen-index-html.js node script/gen-index-html.js
# Temporarily re-create old HTML import # Temporarily re-create old HTML import
@ -20,3 +23,6 @@ cat $OUTPUT_DIR_ES5/chunk.*.js >> $OUTPUT_DIR_ES5/hassio-app.html
echo "</script>" >> $OUTPUT_DIR_ES5/hassio-app.html echo "</script>" >> $OUTPUT_DIR_ES5/hassio-app.html
rm $OUTPUT_DIR_ES5/app.js* rm $OUTPUT_DIR_ES5/app.js*
rm $OUTPUT_DIR_ES5/chunk.* rm $OUTPUT_DIR_ES5/chunk.*
# NEW BUILD
NODE_ENV=production ../node_modules/.bin/webpack -p --config webpack.config.js

View File

@ -4,10 +4,9 @@
# Stop on errors # Stop on errors
set -e set -e
OUTPUT_DIR_ES5=build-es5 OUTPUT_DIR=build
rm -rf $OUTPUT_DIR_ES5 rm -rf $OUTPUT_DIR
mkdir $OUTPUT_DIR_ES5 mkdir $OUTPUT_DIR
node script/gen-index-html.js
node script/gen-icons.js node script/gen-icons.js
../node_modules/.bin/webpack --watch --progress ../node_modules/.bin/webpack --watch --progress

View File

@ -15,4 +15,4 @@ for (item of toReplace) {
index = index.replace(item[0], item[1]); index = index.replace(item[0], item[1]);
} }
fs.writeFileSync(`${config.buildDir}/index.html`, index); fs.writeFileSync(`${config.buildDirLegacy}/index.html`, index);

5
hassio/src/entrypoint.js Normal file
View File

@ -0,0 +1,5 @@
window.loadES5Adapter().then(() => {
import(/* webpackChunkName: "hassio-icons" */ './resources/hassio-icons.js');
import(/* webpackChunkName: "hassio-main" */ './hassio-main.js');
});

View File

@ -2,6 +2,7 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
const config = require('./config.js'); const config = require('./config.js');
const version = fs.readFileSync('../setup.py', 'utf8').match(/\d{8}[^']*/); const version = fs.readFileSync('../setup.py', 'utf8').match(/\d{8}[^']*/);
@ -29,6 +30,15 @@ if (isProdBuild) {
mangle: false, mangle: false,
} }
})); }));
plugins.push(new CompressionPlugin({
cache: true,
exclude: [
/\.js\.map$/,
/\.LICENSE$/,
/\.py$/,
/\.txt$/,
]
}));
} }
module.exports = { module.exports = {
@ -37,7 +47,7 @@ module.exports = {
// Was source-map // Was source-map
devtool: isProdBuild ? 'none' : 'inline-source-map', devtool: isProdBuild ? 'none' : 'inline-source-map',
entry: { entry: {
app: './src/hassio-app.js', entrypoint: './src/entrypoint.js',
}, },
module: { module: {
rules: [ rules: [

View File

@ -0,0 +1,78 @@
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const config = require('./config.js');
const version = fs.readFileSync('../setup.py', 'utf8').match(/\d{8}[^']*/);
if (!version) {
throw Error('Version not found');
}
const VERSION = version[0];
const isProdBuild = process.env.NODE_ENV === 'production'
const chunkFilename = isProdBuild ?
'chunk.[chunkhash].js' : '[name].chunk.js';
const plugins = [
new webpack.DefinePlugin({
__DEV__: JSON.stringify(!isProdBuild),
__VERSION__: JSON.stringify(VERSION),
})
];
if (isProdBuild) {
plugins.push(new UglifyJsPlugin({
extractComments: true,
sourceMap: true,
uglifyOptions: {
// Disabling because it broke output
mangle: false,
}
}));
}
module.exports = {
mode: isProdBuild ? 'production' : 'development',
// Disabled in prod while we make Home Assistant able to serve the right files.
// Was source-map
devtool: isProdBuild ? 'none' : 'inline-source-map',
entry: {
app: './src/hassio-app.js',
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['es2015', { modules: false }]
],
plugins: [
// Only support the syntax, Webpack will handle it.
"syntax-dynamic-import",
],
},
},
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
exportAsEs6Default: true,
}
}
}
]
},
plugins,
output: {
filename: '[name].js',
chunkFilename: chunkFilename,
path: config.buildDirLegacy,
publicPath: `${config.publicPathLegacy}/`,
}
};

View File

@ -9,7 +9,6 @@
"src/panels/dev-service/ha-panel-dev-service.js", "src/panels/dev-service/ha-panel-dev-service.js",
"src/panels/dev-state/ha-panel-dev-state.js", "src/panels/dev-state/ha-panel-dev-state.js",
"src/panels/dev-template/ha-panel-dev-template.js", "src/panels/dev-template/ha-panel-dev-template.js",
"src/panels/hassio/ha-panel-hassio.js",
"src/panels/history/ha-panel-history.js", "src/panels/history/ha-panel-history.js",
"src/panels/iframe/ha-panel-iframe.js", "src/panels/iframe/ha-panel-iframe.js",
"src/panels/kiosk/ha-panel-kiosk.js", "src/panels/kiosk/ha-panel-kiosk.js",
@ -17,7 +16,7 @@
"src/panels/map/ha-panel-map.js", "src/panels/map/ha-panel-map.js",
"src/panels/shopping-list/ha-panel-shopping-list.js", "src/panels/shopping-list/ha-panel-shopping-list.js",
"src/panels/mailbox/ha-panel-mailbox.js", "src/panels/mailbox/ha-panel-mailbox.js",
"hassio/src/hassio-app.js" "hassio/src/entrypoint.js"
], ],
"sources": [ "sources": [
"src/**/*", "src/**/*",

View File

@ -49,10 +49,6 @@ function ensureLoaded(panel) {
imported = import(/* webpackChunkName: "panel-dev-template" */ '../panels/dev-template/ha-panel-dev-template.js'); imported = import(/* webpackChunkName: "panel-dev-template" */ '../panels/dev-template/ha-panel-dev-template.js');
break; break;
case 'hassio':
imported = import(/* webpackChunkName: "panel-hassio" */ '../panels/hassio/ha-panel-hassio.js');
break;
case 'history': case 'history':
imported = import(/* webpackChunkName: "panel-history" */ '../panels/history/ha-panel-history.js'); imported = import(/* webpackChunkName: "panel-history" */ '../panels/history/ha-panel-history.js');
break; break;

View File

@ -1,84 +0,0 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import config from '../../../hassio/config.js';
import EventsMixin from '../../mixins/events-mixin.js';
import NavigateMixin from '../../mixins/navigate-mixin.js';
/*
* Mixins are used by ifram to communicate with main frontend.
* @appliesMixin EventsMixin
* @appliesMixin NavigateMixin
*/
class HaPanelHassio extends NavigateMixin(EventsMixin(PolymerElement)) {
static get template() {
return html`
<style>
iframe {
border: 0;
width: 100%;
height: 100%;
display: block;
}
</style>
<iframe
id='iframe'
src="[[iframeUrl]]"
></iframe>
`;
}
static get properties() {
return {
hass: Object,
narrow: Boolean,
showMenu: Boolean,
route: Object,
iframeUrl: {
type: String,
value: `${config.publicPath}/index.html`
}
};
}
static get observers() {
return [
'_dataChanged(hass, narrow, showMenu, route)'
];
}
ready() {
super.ready();
// Make it available for the iframe to interact
window.hassioPanel = this;
}
_dataChanged(hass, narrow, showMenu, route) {
this._updateProperties({ hass, narrow, showMenu, route });
}
_updateProperties(data) {
const setProperties = this.$.iframe.contentWindow && this.$.iframe.contentWindow.setProperties;
// Delay calling setProperties until iframe loaded
if (!setProperties) {
// Check if we already have a setTimeout scheduled
const needTimeout = !this._dataToSet;
this._dataToSet = data;
if (needTimeout) {
setTimeout(() => {
const dataToSet = this._dataToSet;
this._dataToSet = null;
this._updateProperties(dataToSet);
}, 100);
}
return;
}
setProperties(data);
}
}
customElements.define('ha-panel-hassio', HaPanelHassio);