diff --git a/craco.config.cjs b/craco.config.cjs index 1c5e4f02dc..85d2b1053c 100644 --- a/craco.config.cjs +++ b/craco.config.cjs @@ -5,7 +5,6 @@ const { execSync } = require('child_process') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const path = require('path') const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin') -const TerserPlugin = require('terser-webpack-plugin') const { IgnorePlugin, ProvidePlugin } = require('webpack') const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin') @@ -146,18 +145,20 @@ module.exports = { return rule }) + // Run terser compression on node_modules before tree-shaking, so that tree-shaking is more effective. + // This works by eliminating dead code, so that webpack can identify unused imports and tree-shake them; + // it is only necessary for node_modules - it is done through linting for our own source code - + // see https://medium.com/engineering-housing/dead-code-elimination-and-tree-shaking-at-housing-part-1-307a94b30f23#7e03: + webpackConfig.module.rules.push({ + enforce: 'post', + test: /node_modules.*\.(js)$/, + loader: path.join(__dirname, 'scripts/terser-loader.js'), + options: { compress: true, mangle: false }, + }) + // Configure webpack optimization: webpackConfig.optimization = Object.assign( webpackConfig.optimization, - { - minimize: isProduction, - minimizer: [ - new TerserPlugin({ - minify: TerserPlugin.swcMinify, - parallel: require('os').cpus().length, - }), - ], - }, isProduction ? { splitChunks: { diff --git a/package.json b/package.json index b61d31b030..7e47ec2a96 100644 --- a/package.json +++ b/package.json @@ -152,6 +152,7 @@ "source-map-explorer": "^2.5.3", "start-server-and-test": "^2.0.0", "swc-loader": "^0.2.3", + "terser": "^5.19.4", "terser-webpack-plugin": "^5.3.9", "ts-jest": "^29.1.1", "ts-transform-graphql-tag": "^0.2.1", diff --git a/scripts/terser-loader.js b/scripts/terser-loader.js new file mode 100644 index 0000000000..969068b062 --- /dev/null +++ b/scripts/terser-loader.js @@ -0,0 +1,15 @@ +/* eslint-env node */ + +const { minify } = require('terser') + +module.exports = async function terserLoader(source, map, meta) { + const callback = this.async() + const options = this.getOptions() + try { + const data = await minify(source, options) + const { code } = data || {} + callback(null, code, map, meta) + } catch (e) { + callback(e) + } +} diff --git a/yarn.lock b/yarn.lock index bfd9cad34f..934116c209 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19494,10 +19494,10 @@ terser-webpack-plugin@^5.2.5, terser-webpack-plugin@^5.3.7, terser-webpack-plugi serialize-javascript "^6.0.1" terser "^5.16.8" -terser@^5.0.0, terser@^5.10.0, terser@^5.16.8: - version "5.19.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.2.tgz#bdb8017a9a4a8de4663a7983f45c506534f9234e" - integrity sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA== +terser@^5.0.0, terser@^5.10.0, terser@^5.16.8, terser@^5.19.4: + version "5.19.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.4.tgz#941426fa482bf9b40a0308ab2b3cd0cf7c775ebd" + integrity sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2"