deps: Improve Webpack build performance (#2288)
- Upgrades webpack and webpack tool versions - Updates dev source map to webpack recommendation - Implements `webpack.DllPlugin` in dev for faster rebuilds - Implements `thread-loader` to run `ts-loader` in a worker pool
This commit is contained in:
parent
c53528332b
commit
dd22fd11ee
@ -78,13 +78,14 @@
|
||||
"style-loader": "^3.3.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"thread-loader": "^4.0.4",
|
||||
"ts-loader": "^9.2.6",
|
||||
"tsconfig-paths-webpack-plugin": "^4.1.0",
|
||||
"typescript": "^5.3.3",
|
||||
"update-dotenv": "^1.1.1",
|
||||
"url-pattern": "^1.0.3",
|
||||
"webpack": "^5.88.0",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"webpack": "^5.97.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"yaml": "^2.0.0-11",
|
||||
"zod": "^3.23.8"
|
||||
@ -97,6 +98,7 @@
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"build-dev": "webpack --mode development",
|
||||
"build:analyze": "BUNDLE_ANALYZER=true webpack --config webpack.prod.js",
|
||||
"prestart": "webpack --mode development --config vendor.webpack.config.js",
|
||||
"start": "webpack serve --mode=development --config webpack.dev.js",
|
||||
"serve": "node scripts/serve.js",
|
||||
"lint": "eslint --fix .",
|
||||
@ -120,7 +122,7 @@
|
||||
"sinon": "^12.0.1",
|
||||
"ts-lit-plugin": "^2.0.1",
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-dev-server": "^4.15.0"
|
||||
"webpack-dev-server": "^5.2.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esm-bundle/chai": "^4.3.4-fix.0",
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// @ts-check
|
||||
// Serve app locally without building with webpack, e.g. for e2e
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
@ -15,23 +16,36 @@ require("dotenv").config({
|
||||
path: dotEnvPath,
|
||||
});
|
||||
|
||||
const [devConfig] = require("../webpack.dev.js");
|
||||
const devConfigs = require("../webpack.dev.js");
|
||||
const [devConfig] = devConfigs;
|
||||
|
||||
const app = express();
|
||||
|
||||
const { devServer } = devConfig;
|
||||
/** @type {import('webpack').Configuration['devServer']} */
|
||||
const devServer = devConfig.devServer;
|
||||
|
||||
devServer.setupMiddlewares([], { app });
|
||||
if (!devServer) {
|
||||
throw new Error("Dev server not defined in `webpack.dev.js`");
|
||||
}
|
||||
|
||||
if (devServer.setupMiddlewares) {
|
||||
// @ts-ignore Express app is compatible with `Server`
|
||||
devServer.setupMiddlewares([], { app });
|
||||
}
|
||||
|
||||
if (Array.isArray(devServer.proxy)) {
|
||||
devServer.proxy.forEach((proxy) => {
|
||||
app.use(
|
||||
// @ts-ignore
|
||||
proxy.context,
|
||||
createProxyMiddleware({
|
||||
...proxy,
|
||||
followRedirects: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(devServer.proxy).forEach((path) => {
|
||||
app.use(
|
||||
path,
|
||||
createProxyMiddleware({
|
||||
...devServer.proxy[path],
|
||||
followRedirects: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
app.use("/", express.static(distPath));
|
||||
app.get("/*", (req, res) => {
|
||||
res.sendFile(path.join(distPath, "index.html"));
|
||||
|
||||
@ -19,6 +19,9 @@
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<script src="/extra.js"></script>
|
||||
<%if (environment === "development") { %>
|
||||
<script defer src="/vendor/dll.lit.js"></script>
|
||||
<% } %>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
23
frontend/vendor.webpack.config.js
Normal file
23
frontend/vendor.webpack.config.js
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Separate vendor modules to speed up development rebuild
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
lit: ["lit", "@lit/localize"],
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, "dist/vendor"),
|
||||
filename: "dll.[name].js",
|
||||
library: "[name]_[fullhash]",
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DllPlugin({
|
||||
path: path.join(__dirname, "dist/vendor", "[name]-manifest.json"),
|
||||
name: "[name]_[fullhash]",
|
||||
}),
|
||||
],
|
||||
};
|
||||
@ -5,9 +5,11 @@ const childProcess = require("child_process");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
|
||||
const CopyPlugin = require("copy-webpack-plugin");
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const threadLoader = require("thread-loader");
|
||||
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
|
||||
const webpack = require("webpack");
|
||||
|
||||
@ -15,7 +17,7 @@ const defineConfig = require("./config/define.js");
|
||||
// @ts-ignore
|
||||
const packageJSON = require("./package.json");
|
||||
|
||||
const isDevServer = process.env.WEBPACK_SERVE;
|
||||
const isDevServer = process.env.WEBPACK_SERVE === "true";
|
||||
|
||||
const dotEnvPath = path.resolve(
|
||||
process.cwd(),
|
||||
@ -75,6 +77,20 @@ const version = (() => {
|
||||
return packageJSON.version;
|
||||
})();
|
||||
|
||||
/** @type {Partial<import('ts-loader').Options>} */
|
||||
const tsLoaderOptions = {
|
||||
onlyCompileBundledFiles: true,
|
||||
transpileOnly: true,
|
||||
// Enables compatibility with thread-loader
|
||||
happyPackMode: true,
|
||||
};
|
||||
|
||||
const threadLoaderOptions = {
|
||||
poolTimeout: isDevServer ? Infinity : 2000,
|
||||
};
|
||||
|
||||
threadLoader.warmup(threadLoaderOptions, ["ts-loader"]);
|
||||
|
||||
/** @type {import('webpack').Configuration} */
|
||||
const main = {
|
||||
entry: "./src/index.ts",
|
||||
@ -87,9 +103,11 @@ const main = {
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
// Non-generated source files
|
||||
{
|
||||
test: /\.ts$/,
|
||||
include: path.resolve(__dirname, "src"),
|
||||
exclude: path.resolve(__dirname, "src/__generated__"),
|
||||
use: [
|
||||
{
|
||||
loader: "postcss-loader",
|
||||
@ -100,15 +118,30 @@ const main = {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: "thread-loader",
|
||||
options: threadLoaderOptions,
|
||||
},
|
||||
{
|
||||
loader: "ts-loader",
|
||||
options: {
|
||||
onlyCompileBundledFiles: true,
|
||||
transpileOnly: true,
|
||||
},
|
||||
options: tsLoaderOptions,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Generated source files
|
||||
test: /\.ts$/,
|
||||
include: path.resolve(__dirname, "src/__generated__"),
|
||||
use: [
|
||||
{
|
||||
loader: "thread-loader",
|
||||
options: threadLoaderOptions,
|
||||
},
|
||||
{
|
||||
loader: "ts-loader",
|
||||
options: tsLoaderOptions,
|
||||
},
|
||||
],
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
// Global styles and assets, like fonts and Shoelace,
|
||||
@ -171,6 +204,11 @@ const main = {
|
||||
configOverwrite: {
|
||||
exclude: ["**/*.test.ts", "tests/**/*.ts", "playwright.config.ts"],
|
||||
},
|
||||
// Re-enable type checking when `happyPackMode` is enabled
|
||||
diagnosticOptions: {
|
||||
semantic: true,
|
||||
syntactic: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
// @ts-check
|
||||
|
||||
const path = require("path");
|
||||
|
||||
const ESLintPlugin = require("eslint-webpack-plugin");
|
||||
const webpack = require("webpack");
|
||||
const { merge } = require("webpack-merge");
|
||||
|
||||
const baseConfigs = require("./webpack.config.js");
|
||||
@ -26,9 +26,42 @@ const RWP_BASE_URL =
|
||||
|
||||
const devBackendUrl = new URL(process.env.API_BASE_URL);
|
||||
|
||||
/** @type {import('webpack').Configuration['plugins']} */
|
||||
const plugins = [
|
||||
new ESLintPlugin({
|
||||
extensions: ["ts", "js"],
|
||||
}),
|
||||
];
|
||||
|
||||
// Dev config may be used in Playwright E2E CI tests
|
||||
if (process.env.WEBPACK_SERVE === "true") {
|
||||
let litManifest;
|
||||
|
||||
try {
|
||||
litManifest = require.resolve(
|
||||
path.join(__dirname, "dist/vendor/lit-manifest.json"),
|
||||
);
|
||||
} catch {
|
||||
console.warn(
|
||||
"`lit-manifest.json` not found. If you're seeing this with `yarn start`, ensure the file exists. You can ignore this message otherwise.",
|
||||
);
|
||||
}
|
||||
|
||||
if (litManifest) {
|
||||
plugins.unshift(
|
||||
// Speed up rebuilds by excluding vendor modules
|
||||
new webpack.DllReferencePlugin({
|
||||
manifest: require.resolve(
|
||||
path.join(__dirname, "dist/vendor/lit-manifest.json"),
|
||||
),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = [
|
||||
merge(main, {
|
||||
devtool: "eval-cheap-source-map",
|
||||
devtool: "eval",
|
||||
/** @type {import('webpack-dev-server').Configuration} */
|
||||
devServer: {
|
||||
watchFiles: ["src/**/*", __filename],
|
||||
@ -40,24 +73,30 @@ module.exports = [
|
||||
directory: shoelaceAssetsSrcPath,
|
||||
publicPath: "/" + shoelaceAssetsPublicPath,
|
||||
},
|
||||
{
|
||||
directory: path.join(__dirname, "dist/vendor"),
|
||||
publicPath: "/vendor",
|
||||
},
|
||||
],
|
||||
historyApiFallback: true,
|
||||
proxy: {
|
||||
"/api": {
|
||||
proxy: [
|
||||
{
|
||||
context: "/api",
|
||||
|
||||
target: devBackendUrl.href,
|
||||
headers: {
|
||||
Host: devBackendUrl.host,
|
||||
},
|
||||
ws: true,
|
||||
},
|
||||
|
||||
"/data": {
|
||||
{
|
||||
context: "/data",
|
||||
target: devBackendUrl.href,
|
||||
headers: {
|
||||
Host: devBackendUrl.host,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
setupMiddlewares: (middlewares, server) => {
|
||||
// Serve replay service worker file
|
||||
server.app?.get("/replay/sw.js", (req, res) => {
|
||||
@ -93,11 +132,7 @@ module.exports = [
|
||||
config: [__filename],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new ESLintPlugin({
|
||||
extensions: ["ts", "js"],
|
||||
}),
|
||||
],
|
||||
plugins,
|
||||
}),
|
||||
{
|
||||
...vnc,
|
||||
|
||||
1091
frontend/yarn.lock
generated
1091
frontend/yarn.lock
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user