From 85807e1609990058b7692c737db1c92e8768fe86 Mon Sep 17 00:00:00 2001 From: James ODonnell Date: Tue, 10 Oct 2023 11:54:19 +0100 Subject: [PATCH] [ST-5243] Make splitChunks configurable --- packages/react-scripts/README.md | 1 + .../react-scripts/backpack-addons/README.md | 1 + .../backpack-addons/splitChunks.js | 94 +++++++++++++++---- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index dbea2fae2ef..4963d40d390 100644 --- a/packages/react-scripts/README.md +++ b/packages/react-scripts/README.md @@ -30,6 +30,7 @@ npm start - `babelIncludePrefixes`: An array of module name prefixes to opt into babel compilation, including local import module, e.g. `"../common"`. Includes `["@skyscanner/bpk-", "bpk-", "saddlebag-"]` by default. - `enableAutomaticChunking`: Boolean, opt in to automatic chunking of vendor, common and app code. - `vendorsChunkRegex`: String, Regex for picking what goes into the `vendors` chunk. See `cacheGroups` in webpack docs. Dependent on `enableAutomaticChunking` being enabled + - `splitChunksConfig`: Object, mapping to the [structure in the webpack docs](https://webpack.js.org/plugins/split-chunks-plugin/#optimizationsplitchunks). Applied only if `enableAutomaticChunking` is false, ignores `vendorsChunkRegex` if defined. - `amdExcludes`: Array of module names to exclude from AMD parsing. Incldues `["lodash"]` by default. - `externals`: exposing the Webpack config to modify externals, see [docs](https://webpack.js.org/configuration/externals/). - `ssrExternals`: Similar to above, but for `ssr.js` only. diff --git a/packages/react-scripts/backpack-addons/README.md b/packages/react-scripts/backpack-addons/README.md index f5c4431c08b..1f0e67857b6 100644 --- a/packages/react-scripts/backpack-addons/README.md +++ b/packages/react-scripts/backpack-addons/README.md @@ -14,6 +14,7 @@ Our react scripts fork includes a number of custom configuration items in order | **ssrExternals** | The same as above `externals` except used for server side rendering only in **ssr.js** | **{}** | | **enableAutomaticChunking** | Opts into automatic chunking of vender, common and app code.
When enabled the **splitChunks** plugin creates vender and common chunks which are split and when provided uses the `venderChunkRegex` to specify what is in each chunk.
When enabled **runtimeChunk** plugin creates a separate runtime chunk for projects to enable long term caching. | **false** | | **vendorsChunkRegex** | Regex for picking what goes into the vendors chunk. Requires enableAutomaticChunking to be enabled.
See [cacheGroups](https://webpack.js.org/plugins/split-chunks-plugin/#splitchunkscachegroups) docs for further details. | | +| **splitChunksConfig** | Object, mapping to the [structure in the webpack docs](https://webpack.js.org/plugins/split-chunks-plugin/#optimizationsplitchunks).
Applied only if `enableAutomaticChunking` is false, ignores `vendorsChunkRegex` if defined. | | | **sassFunctions** | This function encodes svg content into `base64` when there is a `bpk-icon` in the.scss file. | | ## How to add new feature diff --git a/packages/react-scripts/backpack-addons/splitChunks.js b/packages/react-scripts/backpack-addons/splitChunks.js index 68591701612..22abea25a04 100644 --- a/packages/react-scripts/backpack-addons/splitChunks.js +++ b/packages/react-scripts/backpack-addons/splitChunks.js @@ -4,23 +4,85 @@ const paths = require('../config/paths'); const appPackageJson = require(paths.appPackageJson); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; +/** + * Defines a webpack splitChunks configuration, optionally based on consumer configuration. + * + * For automatic configuration set enableAutomaticChunking and optionally provide a vendorsChunkRegex string, e.g: + * + * // package.json + * ... + * "backpack-react-scripts": { + * ... + * "enableAutomaticChunking": true, + * "vendorsChunkRegex": "...", + * ... + * } + * ... + * + * For custom configuration disable enableAutomaticChunking and provide a configuration object, e.g: + * + * // package.json + * ... + * "backpack-react-scripts": { + * ... + * "enableAutomaticChunking": false, + * "splitChunksConfig": { + * "chunks": "all", + * ... + * "cacheGroups": { + * "vendors": { + * "test": "..." + * }, + * "customChunk": { + * "test": "..." + * "priority": 100, + * "chunks": "all", + * "name": "customChunk", + * }, + * }, + * ... + * } + * ... + * + * References: + * https://webpack.js.org/plugins/split-chunks-plugin/#optimizationsplitchunks + * https://webpack.js.org/plugins/split-chunks-plugin/#splitchunkscachegroups + * https://twitter.com/wSokra/status/969633336732905474 + * https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 + */ + module.exports = (isEnvDevelopment) => { - // Automatically split vendor and commons - // https://twitter.com/wSokra/status/969633336732905474 - // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 - return { - splitChunks: bpkReactScriptsConfig.enableAutomaticChunking - ? { + + let splitChunksConfig = {} + + // If opted in to automatic chunking, apply default configuration + if (bpkReactScriptsConfig.enableAutomaticChunking) { + splitChunksConfig = { chunks: 'all', name: isEnvDevelopment, - cacheGroups: bpkReactScriptsConfig.vendorsChunkRegex - ? { - vendors: { - test: new RegExp(bpkReactScriptsConfig.vendorsChunkRegex) - }, - } - : {}, - } - : {} + cacheGroups: {}, + }; + // Apply vendorsChunkRegex if provided + if (bpkReactScriptsConfig.vendorsChunkRegex) { + splitChunksConfig.cacheGroups = { + vendors: { + // Regexes are passed as strings in package.json config, but need constructed here. + test: new RegExp(bpkReactScriptsConfig.vendorsChunkRegex), + }, + }; + } } -}; \ No newline at end of file + // If not opted in to automatic chunking, use custom configuration - if defined. + else if(bpkReactScriptsConfig.splitChunksConfig) { + // + splitChunksConfig = { ...bpkReactScriptsConfig.splitChunksConfig, name: isEnvDevelopment} + // Regexes are passed as strings in package.json config, but need constructed here. + for(let cacheGroup of Object.keys(splitChunksConfig.cacheGroups)){ + splitChunksConfig.cacheGroups[cacheGroup].test = new RegExp(splitChunksConfig.cacheGroups[cacheGroup].test); + } + } + + return { + splitChunks: splitChunksConfig + }; +};