Shipping less JavaScript up front is the biggest lever for load performance.
webpack creates separate chunks in three ways:
- Entry points: each entry is its own chunk (duplicating shared code unless you configure sharing).
- Dynamic imports:
import("./chart.js")returns a promise and puts the module and its dependencies in a chunk loaded on demand. Route-level splitting withReact.lazyuses this. - SplitChunksPlugin (
optimization.splitChunks): extracts shared modules and vendor code into common chunks.
Magic comments tune dynamic imports: import(/* webpackChunkName: "chart" */ "./chart.js") names the chunk, webpackPrefetch: true fetches it in idle time, webpackPreload: true loads it in parallel with the parent.
SplitChunksPlugin defaults apply to async chunks only. Set chunks: "all" to also split initial chunks, so vendor code shared by entries is loaded once. Cache groups define how modules are grouped:
defaultVendorscollectsnode_modulesmodules;defaultcollects modules used by at least two chunks.- Add your own, e.g. a
reactgroup for React packages with a higherpriority. minSize(20 KB by default; smaller groups are not split out),maxSize,minChunks,maxAsyncRequestsandmaxInitialRequestslimit how aggressive splitting is.
Inspect the result with webpack-bundle-analyzer. Too many tiny chunks cause request overhead; one giant vendor chunk invalidates the cache on every dependency update.
Example
// src/index.js
document.querySelector("#show-chart").addEventListener("click", async () => {
const { drawChart } = await import(
/* webpackChunkName: "chart", webpackPrefetch: true */ "./chart.js"
);
drawChart();
});
// webpack.config.js (excerpt)
module.exports = {
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
react: {
test: /[\\/]node_modules[\\/](react|react-dom|scheduler)[\\/]/,
name: "react",
priority: 20,
},
},
},
},
};
// Output: main.[hash].js, react.[hash].js, chart.[hash].js (loaded on click)Remember
- Dynamic import() creates on-demand chunks
- Magic comments: webpackChunkName, webpackPrefetch, webpackPreload
splitChunks.chunks: 'all'shares vendor code across entries- Cache groups with priorities control grouping
Watch out for
- Prefetching everything, which wastes bandwidth on chunks users rarely need.