RelativeCI bundle analyzer1 works with any Vite configuration, though some configuration options can make it easier to identify changes between builds and notice regressions quicker.
Use a common pattern with content hashes for filenames
Adding the content hash suffix to asset names helps browsers cache the responses and only request from the server when the content of the asset changes. This method improves the performance for returning users because they only need to download the changed assets.
When comparing asset names between different builds, bundle-stats1 removes the hash and compares the assets by the normalized path. The supported patterns are:
# hex hash**/*.HASH.EXT**/*-HASH.EXT**/*_HASH.EXT**/*~HASH.EXT
# base64url hash**/*.HASH.EXT**/*~HASH.EXT
Vite 4/Rollup 3 default filename pattern (**/*-HEX_HASH.EXT
) is supported by default, though for Vite 5/Rollup 4 we need to configure Rollup to use a supported pattern:
import { defineConfig } from 'vite';import { webpackStats } from 'rollup-plugin-webpack-stats';
export default defineConfig((env) => ({ build: { rollupOptions: { output: { assetFileNames: 'assets/[name].[hash][extname]', chunkFileNames: 'assets/[name].[hash].js', entryFileNames: 'assets/[name].[hash].js', }, }, }, plugins: [ webpackStats(), ],}));
npm run build
vite buildvite v5.0.0 building for production...✓ 1862 modules transformed.dist/index.html 0.31 kB │ gzip: 0.22 kBdist/assets/utils.8L8ZNlhE.css 0.03 kB │ gzip: 0.05 kBdist/assets/index._deYuKRK.css 546.34 kB │ gzip: 66.79 kBdist/assets/repo-list.KTrC4ioP.js 0.55 kB │ gzip: 0.38 kBdist/assets/CloseOutlined.Ac2Sglwr.js 0.66 kB │ gzip: 0.47 kBdist/assets/col.KPyWUTbA.js 4.48 kB │ gzip: 1.84 kBdist/assets/utils.pw5xtUsQ.js 40.12 kB │ gzip: 13.12 kBdist/assets/about._IcwKZoH.js 79.56 kB │ gzip: 26.66 kBdist/assets/repo-details.O1eeDOyK.js 117.49 kB │ gzip: 36.84 kBdist/assets/index.rdoY6xeT.js 414.28 kB │ gzip: 136.95 kB✓ built in 2.94s
Set unique names for asynchronous chunks
Asynchronous chunks defer code loading/execution, decrease the initial JS/CSS size, and improve the loading performance.
By default, Rollup extracts the chunk name from the entry module basename and uses it to generate the asset filename using the output.chunkFileNames
configuration.
Module | Chunk name | Filename |
---|---|---|
./about.tsx await import('./about') | about | assets/about.CONTENT_HASH_1.js |
./home.tsx await import('./home') | home | assets/home.CONTENT_HASH_1.js |
./about/index.tsx await import('./index') | index | assets/index.CONTENT_HASH_2.js |
./home/index.tsx await import('./index') | index | assets/index.CONTENT_HASH_3.js |
For example, when importing from directory index modules, Rollup
extracts multiple chunks with the same name index
:
const RepoDetailsAsync = React.lazy( async () => { // import components/repo-details/index.js const chunk = await import('./components/repo-details'); return { default: chunk.RepoDetails }; },);
const RepoListAsync = React.lazy( async () => { // import components/repo-list/index.js const chunk = await import('./components/repo-list'); return { default: chunk.RepoList }; },);
const AboutAsync = React.lazy( async () => { // import components/about/index.js const chunk = await import('./components/about'); return { default: chunk.About }; },);
npm run build
$ vite buildvite v5.0.0 building for production...dist/index.html 0.31 kB │ gzip: 0.22 kBdist/assets/index.8L8ZNlhE.css 0.03 kB │ gzip: 0.05 kBdist/assets/index._deYuKRK.css 546.34 kB │ gzip: 66.79 kBdist/assets/index.6DnQ4OBO.js 0.55 kB │ gzip: 0.37 kBdist/assets/CloseOutlined.OIXdgtwq.js 0.66 kB │ gzip: 0.47 kBdist/assets/col.3PcwYSue.js 4.48 kB │ gzip: 1.85 kBdist/assets/index.PzG5MeZ4.js 40.12 kB │ gzip: 13.12 kBdist/assets/index.gn3unjAa.js 79.56 kB │ gzip: 26.66 kBdist/assets/index.gEtOlbAq.js 117.49 kB │ gzip: 36.84 kBdist/assets/index.NooaB8q3.js 414.26 kB │ gzip: 136.94 kB✓ built in 2.90s
When generating multiple assets with the same path + basename (e.g., PATH/index-HASH_1.js
, PATH/index-HASH_2.js
), bundle-stats1 is not able to match changed assets between builds and cannot show the chunk module comparison.
To set unique chunk names, you can use the chunkFileNames
option to set the name dynamically based on the available information:
Example: set chunk name and file name based on the parent directory of the entry module
import { defineConfig } from 'vite';import { webpackStats } from 'rollup-plugin-webpack-stats';
export default defineConfig((env) => ({ build: { rollupOptions: { output: { assetFileNames: 'assets/[name].[hash][extname]', entryFileNames: 'assets/[name].[hash].js', chunkFileNames: (chunkInfo) => { if (chunkInfo.name === 'index') { const entryModule = chunkInfo.moduleIds[chunkInfo.moduleIds.length - 1];
const segments = path.dirname(entryModule).split('/'); const segment = segments[segments.length - 1];
chunkInfo.name = segment;
return `assets/component-${segment}.[hash].js`; }
return 'assets/[name].[hash].js'; }, }, }, }, plugins: [ webpackStats(), ],}));
npm run build
$ vite buildvite v5.0.0 building for production...dist/index.html 0.31 kB │ gzip: 0.22 kBdist/assets/repo.8L8ZNlhE.css 0.03 kB │ gzip: 0.05 kBdist/assets/index._deYuKRK.css 546.34 kB │ gzip: 66.79 kBdist/assets/component-repo-list.ugpgMnKd.js 0.56 kB │ gzip: 0.38 kBdist/assets/CloseOutlined.0fpL38AF.js 0.66 kB │ gzip: 0.47 kBdist/assets/col.1yOZU9sX.js 4.48 kB │ gzip: 1.84 kBdist/assets/component-repo.SIhLG6w7.js 40.12 kB │ gzip: 13.12 kBdist/assets/component-about._xXEM7JY.js 79.56 kB │ gzip: 26.66 kBdist/assets/component-repo-details.BUE-6VoT.js 117.50 kB │ gzip: 36.85 kBdist/assets/index.UC00wnqI.js 414.35 kB │ gzip: 136.96 kB✓ built in 3.00s
[1]: bundle-stats is an open-source standalone tool that analyzes webpack/rspack/vite/rollup bundle stats and generates an in-depth report with insights and metrics for assets, modules, and packages. Read more about RelativeCI open source projects