mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 23:36:36 +00:00
Split generic bundle config from webpack config (#5917)
This commit is contained in:
parent
06667455ae
commit
c5b223988a
@ -1,4 +1,4 @@
|
|||||||
const options = ({ latestBuild }) => ({
|
module.exports.options = ({ latestBuild }) => ({
|
||||||
presets: [
|
presets: [
|
||||||
!latestBuild && [require("@babel/preset-env").default, { modules: false }],
|
!latestBuild && [require("@babel/preset-env").default, { modules: false }],
|
||||||
require("@babel/preset-typescript").default,
|
require("@babel/preset-typescript").default,
|
||||||
@ -30,10 +30,11 @@ module.exports.babelLoaderConfig = ({ latestBuild }) => {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
test: /\.m?js$|\.tsx?$/,
|
test: /\.m?js$|\.tsx?$/,
|
||||||
|
// Are already ES5, cause warnings when babelified.
|
||||||
exclude: [require.resolve("@mdi/js/mdi.js"), require.resolve("hls.js")],
|
exclude: [require.resolve("@mdi/js/mdi.js"), require.resolve("hls.js")],
|
||||||
use: {
|
use: {
|
||||||
loader: "babel-loader",
|
loader: "babel-loader",
|
||||||
options: options({ latestBuild }),
|
options: module.exports.options({ latestBuild }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
160
build-scripts/bundle.js
Normal file
160
build-scripts/bundle.js
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
const path = require("path");
|
||||||
|
const env = require("./env.js");
|
||||||
|
const paths = require("./paths.js");
|
||||||
|
|
||||||
|
// Files from NPM Packages that should not be imported
|
||||||
|
module.exports.ignorePackages = [
|
||||||
|
// Bloats bundle and it's not used.
|
||||||
|
path.resolve(require.resolve("moment"), "../locale"),
|
||||||
|
// Part of yaml.js and only used for !!js functions that we don't use
|
||||||
|
require.resolve("esprima"),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Files from NPM packages that we should replace with empty file
|
||||||
|
module.exports.emptyPackages = [
|
||||||
|
// Contains all color definitions for all material color sets.
|
||||||
|
// We don't use it
|
||||||
|
require.resolve("@polymer/paper-styles/color.js"),
|
||||||
|
// Loads stuff from a CDN
|
||||||
|
require.resolve("@polymer/font-roboto/roboto.js"),
|
||||||
|
require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"),
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
|
||||||
|
__DEV__: !isProdBuild,
|
||||||
|
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
|
||||||
|
__VERSION__: JSON.stringify(env.version()),
|
||||||
|
__DEMO__: false,
|
||||||
|
__BACKWARDS_COMPAT__: false,
|
||||||
|
__STATIC_PATH__: "/static/",
|
||||||
|
"process.env.NODE_ENV": JSON.stringify(
|
||||||
|
isProdBuild ? "production" : "development"
|
||||||
|
),
|
||||||
|
...defineOverlay,
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.terserOptions = (latestBuild) => ({
|
||||||
|
safari10: true,
|
||||||
|
ecma: latestBuild ? undefined : 5,
|
||||||
|
});
|
||||||
|
|
||||||
|
const outputPath = (outputRoot, latestBuild) =>
|
||||||
|
path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5");
|
||||||
|
|
||||||
|
const publicPath = (latestBuild) =>
|
||||||
|
latestBuild ? "/frontend_latest/" : "/frontend_es5/";
|
||||||
|
|
||||||
|
/*
|
||||||
|
BundleConfig {
|
||||||
|
// Object with entrypoints that need to be bundled
|
||||||
|
entry: { [name: string]: pathToFile },
|
||||||
|
// Folder where bundled files need to be written
|
||||||
|
outputPath: string,
|
||||||
|
// absolute url-path where bundled files can be found
|
||||||
|
publicPath: string,
|
||||||
|
// extra definitions that we need to replace in source
|
||||||
|
defineOverlay: {[name: string]: value },
|
||||||
|
// if this is a production build
|
||||||
|
isProdBuild: boolean,
|
||||||
|
// If we're targeting latest browsers
|
||||||
|
latestBuild: boolean,
|
||||||
|
// If we're doing a stats build (create nice chunk names)
|
||||||
|
isStatsBuild: boolean,
|
||||||
|
// Names of entrypoints that should not be hashed
|
||||||
|
dontHash: Set<string>
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports.config = {
|
||||||
|
app({ isProdBuild, latestBuild, isStatsBuild }) {
|
||||||
|
return {
|
||||||
|
entry: {
|
||||||
|
service_worker: "./src/entrypoints/service_worker.ts",
|
||||||
|
app: "./src/entrypoints/app.ts",
|
||||||
|
authorize: "./src/entrypoints/authorize.ts",
|
||||||
|
onboarding: "./src/entrypoints/onboarding.ts",
|
||||||
|
core: "./src/entrypoints/core.ts",
|
||||||
|
compatibility: "./src/entrypoints/compatibility.ts",
|
||||||
|
"custom-panel": "./src/entrypoints/custom-panel.ts",
|
||||||
|
},
|
||||||
|
outputPath: outputPath(paths.root, latestBuild),
|
||||||
|
publicPath: publicPath(latestBuild),
|
||||||
|
isProdBuild,
|
||||||
|
latestBuild,
|
||||||
|
isStatsBuild,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
demo({ isProdBuild, latestBuild, isStatsBuild }) {
|
||||||
|
return {
|
||||||
|
entry: {
|
||||||
|
main: path.resolve(paths.demo_dir, "src/entrypoint.ts"),
|
||||||
|
compatibility: path.resolve(
|
||||||
|
paths.polymer_dir,
|
||||||
|
"src/entrypoints/compatibility.ts"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
outputPath: outputPath(paths.demo_root, latestBuild),
|
||||||
|
publicPath: publicPath(latestBuild),
|
||||||
|
defineOverlay: {
|
||||||
|
__VERSION__: JSON.stringify(`DEMO-${env.version()}`),
|
||||||
|
__DEMO__: true,
|
||||||
|
},
|
||||||
|
isProdBuild,
|
||||||
|
latestBuild,
|
||||||
|
isStatsBuild,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
cast({ isProdBuild, latestBuild }) {
|
||||||
|
const entry = {
|
||||||
|
launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (latestBuild) {
|
||||||
|
entry.receiver = path.resolve(
|
||||||
|
paths.cast_dir,
|
||||||
|
"src/receiver/entrypoint.ts"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
entry,
|
||||||
|
outputPath: outputPath(paths.cast_root, latestBuild),
|
||||||
|
publicPath: publicPath(latestBuild),
|
||||||
|
isProdBuild,
|
||||||
|
latestBuild,
|
||||||
|
defineOverlay: {
|
||||||
|
__BACKWARDS_COMPAT__: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
hassio({ isProdBuild, latestBuild }) {
|
||||||
|
if (latestBuild) {
|
||||||
|
throw new Error("Hass.io does not support latest build!");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
entry: {
|
||||||
|
entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"),
|
||||||
|
},
|
||||||
|
outputPath: paths.hassio_root,
|
||||||
|
publicPath: paths.hassio_publicPath,
|
||||||
|
isProdBuild,
|
||||||
|
latestBuild,
|
||||||
|
dontHash: new Set(["entrypoint"]),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
gallery({ isProdBuild, latestBuild }) {
|
||||||
|
return {
|
||||||
|
entry: {
|
||||||
|
entrypoint: path.resolve(paths.gallery_dir, "src/entrypoint.js"),
|
||||||
|
},
|
||||||
|
outputPath: outputPath(paths.gallery_root, latestBuild),
|
||||||
|
publicPath: publicPath(latestBuild),
|
||||||
|
isProdBuild,
|
||||||
|
latestBuild,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
@ -4,12 +4,13 @@ const TerserPlugin = require("terser-webpack-plugin");
|
|||||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||||
const WorkerPlugin = require("worker-plugin");
|
const WorkerPlugin = require("worker-plugin");
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
const env = require("./env.js");
|
|
||||||
const { babelLoaderConfig } = require("./babel.js");
|
const { babelLoaderConfig } = require("./babel.js");
|
||||||
|
const bundle = require("./bundle");
|
||||||
|
|
||||||
const createWebpackConfig = ({
|
const createWebpackConfig = ({
|
||||||
entry,
|
entry,
|
||||||
outputRoot,
|
outputPath,
|
||||||
|
publicPath,
|
||||||
defineOverlay,
|
defineOverlay,
|
||||||
isProdBuild,
|
isProdBuild,
|
||||||
latestBuild,
|
latestBuild,
|
||||||
@ -25,6 +26,7 @@ const createWebpackConfig = ({
|
|||||||
? "cheap-module-source-map"
|
? "cheap-module-source-map"
|
||||||
: "eval-cheap-module-source-map",
|
: "eval-cheap-module-source-map",
|
||||||
entry,
|
entry,
|
||||||
|
node: false,
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
babelLoaderConfig({ latestBuild }),
|
babelLoaderConfig({ latestBuild }),
|
||||||
@ -34,9 +36,6 @@ const createWebpackConfig = ({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
externals: {
|
|
||||||
esprima: "esprima",
|
|
||||||
},
|
|
||||||
optimization: {
|
optimization: {
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new TerserPlugin({
|
new TerserPlugin({
|
||||||
@ -44,10 +43,7 @@ const createWebpackConfig = ({
|
|||||||
parallel: true,
|
parallel: true,
|
||||||
extractComments: true,
|
extractComments: true,
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
terserOptions: {
|
terserOptions: bundle.terserOptions(latestBuild),
|
||||||
safari10: true,
|
|
||||||
ecma: latestBuild ? undefined : 5,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -57,40 +53,40 @@ const createWebpackConfig = ({
|
|||||||
// Only include the JS of entrypoints
|
// Only include the JS of entrypoints
|
||||||
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin(
|
||||||
__DEV__: !isProdBuild,
|
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
|
||||||
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
|
|
||||||
__VERSION__: JSON.stringify(env.version()),
|
|
||||||
__DEMO__: false,
|
|
||||||
__BACKWARDS_COMPAT__: false,
|
|
||||||
__STATIC_PATH__: "/static/",
|
|
||||||
"process.env.NODE_ENV": JSON.stringify(
|
|
||||||
isProdBuild ? "production" : "development"
|
|
||||||
),
|
),
|
||||||
...defineOverlay,
|
new webpack.IgnorePlugin({
|
||||||
|
checkResource(resource, context) {
|
||||||
|
// Only use ignore to intercept imports that we don't control
|
||||||
|
// inside node_module dependencies.
|
||||||
|
if (
|
||||||
|
!context.includes("/node_modules/") ||
|
||||||
|
// calling define.amd will call require("!!webpack amd options")
|
||||||
|
resource.startsWith("!!webpack")
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let fullPath;
|
||||||
|
try {
|
||||||
|
fullPath = resource.startsWith(".")
|
||||||
|
? path.resolve(context, resource)
|
||||||
|
: require.resolve(resource);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error in ignore plugin", resource, context);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bundle.ignorePackages.some((toIgnorePath) =>
|
||||||
|
fullPath.startsWith(toIgnorePath)
|
||||||
|
);
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
// Ignore moment.js locales
|
|
||||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
|
||||||
// Color.js is bloated, it contains all color definitions for all material color sets.
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
new webpack.NormalModuleReplacementPlugin(
|
||||||
/@polymer\/paper-styles\/color\.js$/,
|
new RegExp(bundle.emptyPackages.join("|")),
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||||
),
|
),
|
||||||
// Ignore roboto pointing at CDN. We use local font-roboto-local.
|
],
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
/@polymer\/font-roboto\/roboto\.js$/,
|
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
|
||||||
),
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
/@vaadin\/vaadin-material-styles\/font-roboto\.js$/,
|
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
|
||||||
),
|
|
||||||
// Ignore mwc icons pointing at CDN.
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
/@material\/mwc-icon\/mwc-icon-font\.js$/,
|
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
|
||||||
),
|
|
||||||
].filter(Boolean),
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [".ts", ".js", ".json"],
|
extensions: [".ts", ".js", ".json"],
|
||||||
},
|
},
|
||||||
@ -105,11 +101,8 @@ const createWebpackConfig = ({
|
|||||||
isProdBuild && !isStatsBuild
|
isProdBuild && !isStatsBuild
|
||||||
? "chunk.[chunkhash].js"
|
? "chunk.[chunkhash].js"
|
||||||
: "[name].chunk.js",
|
: "[name].chunk.js",
|
||||||
path: path.resolve(
|
path: outputPath,
|
||||||
outputRoot,
|
publicPath,
|
||||||
latestBuild ? "frontend_latest" : "frontend_es5"
|
|
||||||
),
|
|
||||||
publicPath: latestBuild ? "/frontend_latest/" : "/frontend_es5/",
|
|
||||||
// To silence warning in worker plugin
|
// To silence warning in worker plugin
|
||||||
globalObject: "self",
|
globalObject: "self",
|
||||||
},
|
},
|
||||||
@ -117,94 +110,31 @@ const createWebpackConfig = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||||
return createWebpackConfig({
|
return createWebpackConfig(
|
||||||
entry: {
|
bundle.config.app({ isProdBuild, latestBuild, isStatsBuild })
|
||||||
service_worker: "./src/entrypoints/service_worker.ts",
|
);
|
||||||
app: "./src/entrypoints/app.ts",
|
|
||||||
authorize: "./src/entrypoints/authorize.ts",
|
|
||||||
onboarding: "./src/entrypoints/onboarding.ts",
|
|
||||||
core: "./src/entrypoints/core.ts",
|
|
||||||
compatibility: "./src/entrypoints/compatibility.ts",
|
|
||||||
"custom-panel": "./src/entrypoints/custom-panel.ts",
|
|
||||||
},
|
|
||||||
outputRoot: paths.root,
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
isStatsBuild,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||||
return createWebpackConfig({
|
return createWebpackConfig(
|
||||||
entry: {
|
bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild })
|
||||||
main: path.resolve(paths.demo_dir, "src/entrypoint.ts"),
|
);
|
||||||
compatibility: path.resolve(
|
|
||||||
paths.polymer_dir,
|
|
||||||
"src/entrypoints/compatibility.ts"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
outputRoot: paths.demo_root,
|
|
||||||
defineOverlay: {
|
|
||||||
__VERSION__: JSON.stringify(`DEMO-${env.version()}`),
|
|
||||||
__DEMO__: true,
|
|
||||||
},
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
isStatsBuild,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createCastConfig = ({ isProdBuild, latestBuild }) => {
|
const createCastConfig = ({ isProdBuild, latestBuild }) => {
|
||||||
const entry = {
|
return createWebpackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
|
||||||
launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (latestBuild) {
|
|
||||||
entry.receiver = path.resolve(paths.cast_dir, "src/receiver/entrypoint.ts");
|
|
||||||
}
|
|
||||||
|
|
||||||
return createWebpackConfig({
|
|
||||||
entry,
|
|
||||||
outputRoot: paths.cast_root,
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
defineOverlay: {
|
|
||||||
__BACKWARDS_COMPAT__: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createHassioConfig = ({ isProdBuild, latestBuild }) => {
|
const createHassioConfig = ({ isProdBuild, latestBuild }) => {
|
||||||
if (latestBuild) {
|
return createWebpackConfig(
|
||||||
throw new Error("Hass.io does not support latest build!");
|
bundle.config.hassio({ isProdBuild, latestBuild })
|
||||||
}
|
);
|
||||||
const config = createWebpackConfig({
|
|
||||||
entry: {
|
|
||||||
entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"),
|
|
||||||
},
|
|
||||||
outputRoot: "",
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
dontHash: new Set(["entrypoint"]),
|
|
||||||
});
|
|
||||||
|
|
||||||
config.output.path = paths.hassio_root;
|
|
||||||
config.output.publicPath = paths.hassio_publicPath;
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createGalleryConfig = ({ isProdBuild, latestBuild }) => {
|
const createGalleryConfig = ({ isProdBuild, latestBuild }) => {
|
||||||
const config = createWebpackConfig({
|
return createWebpackConfig(
|
||||||
entry: {
|
bundle.config.gallery({ isProdBuild, latestBuild })
|
||||||
entrypoint: path.resolve(paths.gallery_dir, "src/entrypoint.js"),
|
);
|
||||||
},
|
|
||||||
outputRoot: paths.gallery_root,
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
});
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user