RelativeCI does not require a specific webpack configuration, but some options can make it easier to identify changes between builds. Other than improving monitoring, some of the following webpack configuration options are also recommended for long-term caching.
Use a common pattern for filename content hashes
Adding the content hash suffix to file names helps browsers cache the assets and only request the asset from the server when the content changes. This method improves the experience for returning users who only need to download the changed assets.
When comparing asset names between different builds, bundle-stats extracts the content hash and compares the assets by source file name. The most common supported patterns are:
file-HASH.jsfile.HASH.js
To configure asset file names, you can set the following options for the production mode config:
module.exports = { output: { // Configure entry file names filename: '[name].[contenthash].js', // Configure chunk file names chunkFilename: '[name].[chunkhash].js', // Configure asset file names assetModuleFilename: '[path][name].[contenthash][ext][query]' }, plugins: [ // CSS file name pattern when using mini-css-extract-plugin new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }) ]}
assets by path *.js 10.5 KiB asset vendors.f1eef34c98603711f45e.js 8.71 KiB [emitted] [immutable] [minimized] (name: vendors) (id hint: vendors) asset main.7c920d907e4c753d0935.js 1.79 KiB [emitted] [immutable] [minimized] (name: main)asset images/logo.31b9235056a3dc35c4c5.png 6.4 KiB [emitted] [immutable] [from: images/logo.png] (auxiliary name: main)asset index.html 364 bytes [emitted]asset main.b231cc1c6e07b9d4ff06.css 122 bytes [emitted] [immutable] (name: main)
module.exports = { output: { // Configure entry file names filename: '[name].[contenthash].js', // Configure chunk file names chunkFilename: '[name].[chunkhash].js' }, module: { rules: [ // file name pattern when using file-loader { test: /\.(png|jpe?g|gif)$/i, loader: 'file-loader', options: { name: '[path][name].[contenthash].[ext]' } } ] }, plugins: [ // CSS file name pattern when using mini-css-extract-plugin new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }) ]}
Asset Size Chunks Chunk Namesimages/logo.31b9235056a3dc35c4c5d9806ab46e4f.png 6.4 KiB [emitted] [immutable] index.html 336 bytes [emitted] main.63b96e941d400fc1b806.css 122 bytes 0 [emitted] [immutable] main main.d7df904f48c9631839e8.js 1.75 KiB 0 [emitted] [immutable] main vendors.0e025fde233b62c30823.js 8.72 KiB 1 [emitted] [immutable] vendors
You can adjust the hash length globally using output.hashDigestLength
option (default 20
). bundle-stats hash replacement supports a minimum of 5 characters.
Name asynchronous chunks
Asynchronous chunks defer code loading/execution, decrease the initial JS/CSS size and improve the loading performance. By default, webpack uses the chunk ID for the chunk file name. When the chunk ID changes, the chunk name will be different, forcing the users to re-download the asset even if there are no code changes.
To output predictable asset names for chunks, use webpack annotation for async chunks:
const HomePageComponent = React.lazy( () => import(/* webpackChunkName: 'home' */'./pages/home'));
const DetailsPage = Loadable({ loader: () => import(/* webpackChunkName: 'details' */'./pages/details'), loading: Loading});
Use deterministic chunkIds (webpack 4)
By default, webpack 4 generates chunk IDs based on their order of appearance('natural' algorithm). The chunk IDs map can change across related chunks when the order changes or a chunk is added/removed. The change is causing unnecessary cache invalidation and does not allow RelativeCI to compare the chunk modules between different builds.
To generate deterministic chunk ids between different builds, you can use optimization.chunkIds
option:
module.exports = { optimization: { chunkIds: 'named' }}
Webpack 5 uses default option chunkIds: 'deterministic'
Read more