More cleanup (#1185)

* More cleanup

* Set up correct urls authorize.html

* Fix polymer lint

* Remove reference to bower

* Tweak uglify settings
This commit is contained in:
Paulus Schoutsen 2018-05-17 17:51:07 -04:00 committed by GitHub
parent cb0db95abe
commit bc27f854f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 151 additions and 247 deletions

View File

@ -1,6 +1,4 @@
node_modules
bower_components
hass_frontend
build
build-temp
hass_frontend_es5
.git

View File

@ -1,16 +1,11 @@
# Home Assistant Polymer [![Build Status](https://travis-ci.org/home-assistant/home-assistant-polymer.svg?branch=master)](https://travis-ci.org/home-assistant/home-assistant-polymer)
This is the repository for the official [Home Assistant](https://home-assistant.io) frontend. The frontend is built on top of the following technologies:
* [Websockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
* [Polymer](https://www.polymer-project.org/)
* [Rollup](http://rollupjs.org/) to package Home Assistant JS
* [Bower](https://bower.io) for Polymer package management
This is the repository for the official [Home Assistant](https://home-assistant.io) frontend.
[![Screenshot of the frontend](https://raw.githubusercontent.com/home-assistant/home-assistant-polymer/master/docs/screenshot.png)](https://home-assistant.io/demo/)
[View demo of the Polymer frontend](https://home-assistant.io/demo/)
[More information about Home Assistant](https://home-assistant.io)
[View demo of the Polymer frontend](https://home-assistant.io/demo/)
[More information about Home Assistant](https://home-assistant.io)
[Frontend development instructions](https://home-assistant.io/developers/frontend/)
## License

View File

@ -1,57 +0,0 @@
const {
Analyzer,
FSUrlLoader
} = require('polymer-analyzer');
const Bundler = require('polymer-bundler').Bundler;
const parse5 = require('parse5');
const { streamFromString } = require('./stream');
// Bundle an HTML file and convert it to a stream
async function bundledStreamFromHTML(path, bundlerOptions = {}) {
const bundler = new Bundler(bundlerOptions);
const manifest = await bundler.generateManifest([path]);
const result = await bundler.bundle(manifest);
return streamFromString(path, parse5.serialize(result.documents.get(path).ast));
}
async function analyze(root, paths) {
const analyzer = new Analyzer({
urlLoader: new FSUrlLoader(root),
});
return analyzer.analyze(paths);
}
async function findDependencies(root, element) {
const deps = new Set();
async function resolve(files) {
const analysis = await analyze(root, files);
const toResolve = [];
for (const file of files) {
const doc = analysis.getDocument(file);
for (const importEl of doc.getFeatures({ kind: 'import' })) {
const url = importEl.url;
if (!deps.has(url)) {
deps.add(url);
toResolve.push(url);
}
}
}
if (toResolve.length > 0) {
return resolve(toResolve);
}
}
await resolve([element]);
return deps;
}
module.exports = {
bundledStreamFromHTML,
findDependencies,
};

View File

@ -1,33 +0,0 @@
/**
* Polymer build strategy to strip imports, even if explictely imported
*/
module.exports.stripImportsStrategy = function (urls) {
return (bundles) => {
for (const bundle of bundles) {
for (const url of urls) {
bundle.stripImports.add(url);
}
}
return bundles;
};
};
/**
* Polymer build strategy to strip everything but the entrypoints
* for bundles that match a specific entry point.
*/
module.exports.stripAllButEntrypointStrategy = function (entryPoint) {
return (bundles) => {
for (const bundle of bundles) {
if (bundle.entrypoints.size === 1 &&
bundle.entrypoints.has(entryPoint)) {
for (const file of bundle.files) {
if (!bundle.entrypoints.has(file)) {
bundle.stripImports.add(file);
}
}
}
}
return bundles;
};
};

View File

@ -1,21 +0,0 @@
const stream = require('stream');
const gutil = require('gulp-util');
function streamFromString(filename, string) {
var src = stream.Readable({ objectMode: true });
src._read = function () {
this.push(new gutil.File({
cwd: '',
base: '',
path: filename,
contents: Buffer.from(string)
}));
this.push(null);
};
return src;
}
module.exports = {
streamFromString,
};

View File

@ -1,11 +1,12 @@
const gulpif = require('gulp-if');
const babel = require('gulp-babel');
const uglify = require('./gulp-uglify.js');
const { gulp: cssSlam } = require('css-slam');
const htmlMinifier = require('gulp-html-minifier');
const { HtmlSplitter } = require('polymer-build');
const pump = require('pump');
const uglify = require('./gulp-uglify.js');
module.exports.minifyStream = function (stream, es6) {
const sourcesHtmlSplitter = new HtmlSplitter();
return pump([

View File

@ -1,28 +0,0 @@
const gulp = require('gulp');
const path = require('path');
const replace = require('gulp-batch-replace');
const rename = require('gulp-rename');
const config = require('../config');
const minifyStream = require('../common/transform').minifyStream;
const {
bundledStreamFromHTML,
} = require('../common/html');
const es5Extra = "<script src='/frontend_es5/custom-elements-es5-adapter.js'></script>";
async function buildAuth(es6) {
const frontendPath = es6 ? 'frontend_latest' : 'frontend_es5';
const stream = gulp.src(path.resolve(config.polymer_dir, 'src/authorize.html'))
.pipe(replace([
['<!--EXTRA_SCRIPTS-->', es6 ? '' : es5Extra],
['/home-assistant-polymer/hass_frontend/authorize.js', `/${frontendPath}/authorize.js`],
]));
return minifyStream(stream, /* es6= */ es6)
.pipe(rename('authorize.html'))
.pipe(gulp.dest(es6 ? config.output : config.output_es5));
}
gulp.task('authorize-es5', () => buildAuth(/* es6= */ false));
gulp.task('authorize', () => buildAuth(/* es6= */ true));

View File

@ -0,0 +1,43 @@
const gulp = require('gulp');
const path = require('path');
const replace = require('gulp-batch-replace');
const rename = require('gulp-rename');
const md5 = require('../common/md5');
const url = require('url');
const config = require('../config');
const minifyStream = require('../common/transform').minifyStream;
const buildReplaces = {
'/frontend_latest/authorize.js': 'authorize.js',
};
const es5Extra = "<script src='/frontend_es5/custom-elements-es5-adapter.js'></script>";
async function buildAuth(es6) {
const targetPath = es6 ? config.output : config.output_es5;
const targetUrl = es6 ? '/frontend_latest/' : '/frontend_es5/';
const frontendPath = es6 ? 'frontend_latest' : 'frontend_es5';
const toReplace = [
['<!--EXTRA_SCRIPTS-->', es6 ? '' : es5Extra],
['/home-assistant-polymer/hass_frontend/authorize.js', `/${frontendPath}/authorize.js`],
];
for (const [replaceSearch, filename] of Object.entries(buildReplaces)) {
const parsed = path.parse(filename);
const hash = md5(path.resolve(targetPath, filename));
toReplace.push([
replaceSearch,
url.resolve(targetUrl, `${parsed.name}-${hash}${parsed.ext}`)]);
}
const stream = gulp.src(path.resolve(config.polymer_dir, 'src/authorize.html'))
.pipe(replace(toReplace));
return minifyStream(stream, /* es6= */ es6)
.pipe(rename('authorize.html'))
.pipe(gulp.dest(es6 ? config.output : config.output_es5));
}
gulp.task('gen-authorize-html-es5', () => buildAuth(/* es6= */ false));
gulp.task('gen-authorize-html', () => buildAuth(/* es6= */ true));

View File

@ -7,8 +7,8 @@ const md5 = require('../common/md5');
const { minifyStream } = require('../common/transform');
const buildReplaces = {
'/home-assistant-polymer/hass_frontend/core.js': 'core.js',
'/home-assistant-polymer/hass_frontend/app.js': 'app.js',
'/frontend_latest/core.js': 'core.js',
'/frontend_latest/app.js': 'app.js',
};
function generateIndex(es6) {
@ -18,7 +18,7 @@ function generateIndex(es6) {
const toReplace = [
// Needs to look like a color during CSS minifiaction
['{{ theme_color }}', '#THEME'],
['/home-assistant-polymer/hass_frontend/mdi.html',
['/static/mdi.html',
`/static/mdi-${md5(path.resolve(config.output, 'mdi.html'))}.html`],
];

View File

@ -1,6 +1,7 @@
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}[^']*/);
@ -12,8 +13,27 @@ const isProdBuild = process.env.NODE_ENV === 'production'
const chunkFilename = isProdBuild ?
'[name]-[chunkhash].chunk.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',
devtool: isProdBuild ? 'source-map ' : 'inline-source-map',
entry: {
app: './src/hassio-app.js',
},
@ -36,16 +56,11 @@ module.exports = {
}
]
},
plugins: [
new webpack.DefinePlugin({
__DEV__: JSON.stringify(!isProdBuild),
__VERSION__: JSON.stringify(VERSION),
})
],
plugins,
output: {
filename: '[name].js',
chunkFilename: chunkFilename,
path: config.buildDir,
publicPath: config.publicPath,
publicPath: `${config.publicPath}/`,
}
};

View File

@ -9,7 +9,7 @@
<link rel='apple-touch-icon' sizes='180x180'
href='/static/icons/favicon-apple-180x180.png'>
<link rel="mask-icon" href="/static/icons/mask-icon.svg" color="#3fbbf4">
<link rel='preload' href='/home-assistant-polymer/hass_frontend/core.js' as='script'/>
<link rel='preload' href='/frontend_latest/core.js' as='script'/>
<link rel='preload' href='/static/fonts/roboto/Roboto-Regular.ttf' as='font' crossorigin />
<link rel='preload' href='/static/fonts/roboto/Roboto-Medium.ttf' as='font' crossorigin />
<meta name='apple-mobile-web-app-capable' content='yes'>
@ -82,28 +82,24 @@
<script>
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
var e = document.createElement('script');
e.onerror = initError;
e.src = '/static/webcomponents-bundle.js';
if ('import' in document.createElement('link')) {
(function() {
var e = document.createElement('script');
e.src = '/static/webcomponents-bundle.js';
document.write(e.outerHTML);
} else {
document.head.appendChild(e);
}
}());
}
/* if ('serviceWorker' in navigator) {
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/service_worker.js');
});
} */
}
</script>
<!--EXTRA_SCRIPTS-->
<script src='/home-assistant-polymer/hass_frontend/core.js'></script>
<script src='/home-assistant-polymer/hass_frontend/app.js'></script>
<link rel='import' href='/home-assistant-polymer/hass_frontend/mdi.html' async>
<script src='/frontend_latest/core.js'></script>
<script src='/frontend_latest/app.js'></script>
<link rel='import' href='/static/mdi.html' async>
{% for extra_url in extra_urls -%}
<link rel='import' href='{{ extra_url }}' async>
{% endfor -%}

View File

@ -137,6 +137,7 @@
"sw-precache": "^5.2.0",
"uglify-es": "^3.1.9",
"uglify-js": "^3.1.9",
"uglifyjs-webpack-plugin": "^1.2.5",
"wct-browser-legacy": "^1.0.0",
"web-component-tester": "^6.6.0",
"webpack": "^4.8.1",

View File

@ -1,6 +1,6 @@
{
"entrypoint": "index.html",
"shell": "src/home-assistant.js",
"shell": "src/entrypoints/app.js",
"fragments": [
"src/panels/config/ha-panel-config.js",
"src/panels/dev-event/ha-panel-dev-event.js",

File diff suppressed because one or more lines are too long

View File

@ -15,24 +15,22 @@ mkdir $OUTPUT_DIR_ES5
cp -r public/__init__.py $OUTPUT_DIR_ES5/
# Build frontend
BUILD_DEV=0 ./node_modules/.bin/gulp build-translations authorize authorize-es5
NODE_ENV=production ./node_modules/.bin/webpack -p
BUILD_DEV=0 ./node_modules/.bin/gulp build-translations
NODE_ENV=production ./node_modules/.bin/webpack
# Icons
script/update_mdi.py
./node_modules/.bin/gulp compress
# Stub the service worker
touch $OUTPUT_DIR/service_worker.js
touch $OUTPUT_DIR_ES5/service_worker.js
# Generate the __init__ file
echo "VERSION = '`git rev-parse HEAD`'" >> $OUTPUT_DIR/__init__.py
echo "CREATED_AT = `date +%s`" >> $OUTPUT_DIR/__init__.py
echo "VERSION = '`git rev-parse HEAD`'" >> $OUTPUT_DIR_ES5/__init__.py
echo "CREATED_AT = `date +%s`" >> $OUTPUT_DIR_ES5/__init__.py
# Generate the MD5 hash of the new frontend
./node_modules/.bin/gulp gen-index-html
./node_modules/.bin/gulp gen-index-html-es5
# Generate index.htmls with the MD5 hash of the builds
./node_modules/.bin/gulp \
gen-index-html gen-index-html-es5 \
gen-authorize-html gen-authorize-html-es5

View File

@ -5,16 +5,22 @@
set -e
OUTPUT_DIR=hass_frontend
OUTPUT_DIR_ES5=hass_frontend_es5
rm -rf $OUTPUT_DIR
rm -rf $OUTPUT_DIR $OUTPUT_DIR_ES5
cp -r public $OUTPUT_DIR
mkdir $OUTPUT_DIR_ES5
# Needed in case frontend repo installed with pip3 install -e
cp -r public/__init__.py $OUTPUT_DIR_ES5/
./node_modules/.bin/gulp build-translations authorize authorize-es5
./node_modules/.bin/gulp build-translations
cp src/authorize.html $OUTPUT_DIR
# Manually copy over this file as we don't run the ES5 build
# The Hass.io panel depends on it.
cp node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js $OUTPUT_DIR_ES5
# Icons
script/update_mdi.py
# Stub the service worker
touch $OUTPUT_DIR/service_worker.js
./node_modules/.bin/webpack --watch --progress

View File

@ -8,19 +8,15 @@
<body>
<ha-authorize>Loading</ha-authorize>
<script>
function addScript(src) {
var e = document.createElement('script');
e.src = src;
document.head.appendChild(e);
}
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
addScript('/static/webcomponents-lite.js');
var e = document.createElement('script');
e.src = '/static/webcomponents-bundle.js';
document.write(e.outerHTML);
}
</script>
<script src="/home-assistant-polymer/hass_frontend/authorize.js"></script>
<script src="/frontend_latest/authorize.js"></script>
</body>
</html>

View File

@ -8,22 +8,22 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { setPassiveTouchGestures } from '@polymer/polymer/lib/utils/settings.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import translationMetadata from '../build-translations/translationMetadata.json';
import './layouts/home-assistant-main.js';
import './layouts/login-form.js';
import './managers/notification-manager.js';
import './resources/ha-style.js';
import './resources/html-import/polyfill.js';
import './util/ha-pref-storage.js';
import './util/hass-call-api.js';
import './util/hass-translation.js';
import './util/legacy-support';
import './util/roboto.js';
import translationMetadata from '../../build-translations/translationMetadata.json';
import '../layouts/home-assistant-main.js';
import '../layouts/login-form.js';
import '../managers/notification-manager.js';
import '../resources/ha-style.js';
import '../resources/html-import/polyfill.js';
import '../util/ha-pref-storage.js';
import '../util/hass-call-api.js';
import '../util/hass-translation.js';
import '../util/legacy-support';
import '../util/roboto.js';
// For mdi icons.
import './components/ha-iconset-svg.js';
import '../components/ha-iconset-svg.js';
import computeStateName from './common/entity/compute_state_name.js';
import applyThemesOnElement from './common/dom/apply_themes_on_element.js';
import computeStateName from '../common/entity/compute_state_name.js';
import applyThemesOnElement from '../common/dom/apply_themes_on_element.js';
setPassiveTouchGestures(true);
/* LastPass createElement workaround. See #428 */

View File

@ -4,8 +4,8 @@ import '@polymer/polymer/lib/elements/dom-repeat.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './ha-auth-flow.js';
import './ha-pick-auth-provider.js';
import '../auth/ha-auth-flow.js';
import '../auth/ha-pick-auth-provider.js';
class HaAuthorize extends PolymerElement {
static get template() {

View File

@ -1,8 +1,8 @@
import * as HAWS from 'home-assistant-js-websocket';
import fetchToken from './common/auth/fetch_token.js';
import refreshToken_ from './common/auth/refresh_token.js';
import parseQuery from './common/util/parse_query.js';
import fetchToken from '../common/auth/fetch_token.js';
import refreshToken_ from '../common/auth/refresh_token.js';
import parseQuery from '../common/util/parse_query.js';
window.HAWS = HAWS;

View File

@ -7,7 +7,7 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../util/hass-attributes-util.js';
import './ha-form-customize-attributes.js';
import computeDomain from '../../../common/entity/compute_domain';
import computeStateDomain from '../../../common/entity/compute_state_domain';
class HaFormCustomize extends PolymerElement {
static get template() {
@ -120,7 +120,7 @@ class HaFormCustomize extends PolymerElement {
attribute: key,
value: value,
closed: false,
domain: computeDomain(this.entity),
domain: computeStateDomain(this.entity),
secondary: secondary,
description: key,
}, config);
@ -200,7 +200,7 @@ class HaFormCustomize extends PolymerElement {
.filter((key) => {
const conf = window.hassAttributeUtil.LOGIC_STATE_ATTRIBUTES[key];
return conf && (!conf.domains || !this.entity ||
conf.domains.includes(computeDomain(this.entity)));
conf.domains.includes(computeStateDomain(this.entity)));
})
.filter(this.filterFromAttributes(localAttributes))
.filter(this.filterFromAttributes(globalAttributes))

View File

@ -59,9 +59,7 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) {
super.connectedCallback();
var map = this._map = Leaflet.map(this.$.map);
var style = document.createElement('link');
style.setAttribute('href', __DEV__ ?
'/home-assistant-polymer/bower_components/leaflet/dist/leaflet.css' :
'/static/images/leaflet/leaflet.css');
style.setAttribute('href', '/static/images/leaflet/leaflet.css');
style.setAttribute('rel', 'stylesheet');
this.$.map.parentNode.appendChild(style);
map.setView([51.505, -0.09], 13);

View File

@ -1,6 +1,7 @@
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const version = fs.readFileSync('setup.py', 'utf8').match(/\d{8}[^']*/);
@ -11,18 +12,12 @@ const VERSION = version[0];
function createConfig(isProdBuild, latestBuild) {
let buildPath = latestBuild ? 'hass_frontend/' : 'hass_frontend_es5/';
let publicPath;
if (isProdBuild) {
publicPath = latestBuild ? '/frontend_latest/' : '/frontend_es5/';
} else {
publicPath = `/home-assistant-polymer/${buildPath}`;
}
const publicPath = latestBuild ? '/frontend_latest/' : '/frontend_es5/';
const entry = {
app: './src/home-assistant.js',
authorize: './src/auth/ha-authorize.js',
core: './src/core.js',
app: './src/entrypoints/app.js',
authorize: './src/entrypoints/authorize.js',
core: './src/entrypoints/core.js',
};
const babelOptions = {
@ -53,6 +48,7 @@ function createConfig(isProdBuild, latestBuild) {
'node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js',
{ from: 'node_modules/leaflet/dist/leaflet.css', to: `images/leaflet/` },
{ from: 'node_modules/leaflet/dist/images', to: `images/leaflet/` },
{ from: 'gulp/service-worker.js.tmpl', to: 'service_worker.js' },
]));
} else {
plugins.push(CopyWebpackPlugin([
@ -61,7 +57,18 @@ function createConfig(isProdBuild, latestBuild) {
babelOptions.presets = [
['es2015', { modules: false }]
];
entry.compatibility = './src/compatibility.js';
entry.compatibility = './src/entrypoints/compatibility.js';
}
if (isProdBuild) {
plugins.push(new UglifyJsPlugin({
extractComments: true,
sourceMap: true,
uglifyOptions: {
// Disabling because it broke output
mangle: false,
}
}));
}
const chunkFilename = isProdBuild ?
@ -69,6 +76,7 @@ function createConfig(isProdBuild, latestBuild) {
return {
mode: isProdBuild ? 'production' : 'development',
devtool: isProdBuild ? 'source-map ' : 'inline-source-map',
entry,
module: {
rules: [

View File

@ -11981,7 +11981,7 @@ uglify-to-browserify@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
uglifyjs-webpack-plugin@^1.2.4:
uglifyjs-webpack-plugin@^1.2.4, uglifyjs-webpack-plugin@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz#2ef8387c8f1a903ec5e44fa36f9f3cbdcea67641"
dependencies: