Large webpack builds can take minutes; understanding the internals points to the real fixes.
Inside a compilation, webpack builds a module graph (modules and their dependency edges), then a chunk graph (which modules belong to which chunks, and how chunk groups load each other). The runtime in the output implements __webpack_require__: a module cache, a registry of module factory functions, and chunk loading via JSONP-style script tags or import() for ESM output. Reading a development bundle (devtool: false, mode: "development") makes all of this visible.
Where time goes in slow builds, usually:
- Loaders, especially Babel and
ts-loaderwith type checking. Replace withswc-loaderoresbuild-loader, and type-check in a separate process (fork-ts-checker-webpack-pluginortsc --noEmit). - Minification: use the SWC or esbuild minifier via
TerserPlugin.swcMinify/esbuildMinify. - Source maps: expensive variants in development.
- Too much work: missing
include/excludeon rules, largeresolve.extensions, building unused locales (moment.js), and no persistent cache.
Measure before changing: npx webpack --profile --json > stats.json for the analyzer, speed-measure-webpack-plugin for per-loader timings, and ProgressPlugin for phase timing.
When a codebase outgrows these fixes, Rspack (Rust, webpack-compatible API and most loaders/plugins) often gives 5-10x faster builds with modest migration effort, while new projects typically choose Vite.
Example
// Simplified view of what webpack's runtime does (development output)
var __webpack_modules__ = {
"./src/greet.js": (module, exports, __webpack_require__) => {
exports.greet = (n) => `Hello, ${n}`;
},
"./src/index.js": (module, exports, __webpack_require__) => {
const { greet } = __webpack_require__("./src/greet.js");
console.log(greet("Ann"));
},
};
var __webpack_module_cache__ = {};
function __webpack_require__(id) {
if (__webpack_module_cache__[id]) return __webpack_module_cache__[id].exports;
const module = (__webpack_module_cache__[id] = { exports: {} });
__webpack_modules__[id](module, module.exports, __webpack_require__);
return module.exports;
}
__webpack_require__("./src/index.js"); // Hello, Ann
// Faster builds: { loader: "swc-loader" } instead of babel-loader,
// cache: { type: "filesystem" }, and npx webpack --profile --json > stats.jsonRemember
- Module graph -> chunk graph -> runtime with __webpack_require__
- Loaders, minifiers and source maps dominate build time
- Profile with --profile --json and per-loader timings
- Rspack is the drop-in path to much faster builds
Watch out for
- Optimizing config blindly without profiling which loader or plugin is slow.