Performance-Fresser ■ Episode 13
In 2012, JavaScript had a module problem. The browser did not understand
require(). Node.js used CommonJS. AMD existed for those with a
particular appetite for acronyms. And somewhere in between, a developer named
Tobias Koppers built a tool that could take all these competing module formats,
resolve their dependency graphs, and emit a single file the browser could execute.
It was called Webpack, and it was, at the time, genuinely useful.
In 2017, ES Modules shipped natively in every major browser. The problem Webpack
was built to solve (that browsers could not understand module imports)
ceased to exist. import and export became part of the
language. The browser understood them. The build step became optional.
It is now 2026. Webpack is nine years older than the problem it solves. And yet 86% of JavaScript developers still use it. The bundler that bundles your patience.
The Build That Time Forgot
Evan Wallace released esbuild in 2020, written in Go, and published benchmarks that read less like a comparison and more like an autopsy report. Three.js, a substantial, real-world codebase, bundled in 0.39 seconds by esbuild. Webpack 5 required 41.21 seconds. That is not a percentage improvement. That is a 106x difference.
The TypeScript compiler for the Rome project: esbuild managed 0.10 seconds. Webpack 5 needed 16.69 seconds. A factor of 167. One hundred and sixty-seven times slower, to produce the same output, from the same input, on the same machine.
One might argue that benchmarks are synthetic, that real-world projects differ, that context matters. One would be correct about all three. And yet, when the magnitude is a hundred-fold, context becomes a footnote. Webpack is not slightly slower. It is categorically slower, in the way that a horse-drawn carriage is categorically slower than an aeroplane. Both reach the destination. One of them allows you to have lunch first.
The Memory Hole
Build time is the visible cost. Memory consumption is the one nobody watches until the CI server falls over.
Webpack 4, on a mid-sized production project, consumed between 500 and 800 MB of RAM. Unpleasant, but manageable. Webpack 5, the version marketed as the performance upgrade, consumed 3.8 GB on the same project. Not a different project. Not a larger codebase. The same files, the same output, and nearly five times the memory.
The root cause is terser-webpack-plugin, Webpack’s default
minifier. It spawns worker threads for parallel minification, a sensible
optimisation in theory. In practice, each worker clones the entire AST into its
own memory space. Four workers, four copies of the abstract syntax tree, four times
the allocation, and a garbage collector that cannot reclaim any of it until all
workers complete. The parallelism that was supposed to save time costs memory
instead, and the trade-off was made without asking.
GitLab’s development environment, powered by Webpack, has been documented at 30 GB of RAM. Thirty gigabytes. For a development environment. For a tool whose job is to concatenate files.
The Developer Experience Tax
A developer’s day begins with a cold start. Open the project, start the dev server, wait. How long one waits depends, rather dramatically, on the bundler.
Vite, built on esbuild for dependency pre-bundling and native ES Modules for serving, cold-starts a project with a thousand React components in 1.7 seconds. Webpack 5, on the same project, requires 5.6 seconds. Three times slower to reach the point where development can begin.
But cold starts happen once. Hot Module Replacement happens hundreds of times a day, every save, every change, every iteration. This is where the tax becomes a salary deduction.
Vite updates the browser in 10 to 20 milliseconds. Webpack takes 500 to 1,600 milliseconds. On every single save. Two hundred saves a day, a conservative estimate for an active developer, and Webpack costs three minutes and twenty seconds of dead air. Not thinking time. Not debugging. Staring at a browser that has not yet caught up with the code you wrote two seconds ago.
Multiply by a team of twenty. Multiply by two hundred and fifty working days. The figure stops being an inconvenience and starts appearing on a spreadsheet.
The Configuration Cathedral
esbuild’s configuration for a production build fits in a function call. Webpack’s configuration is a Gothic cathedral of loaders, plugins, rules, resolve aliases, optimisation strategies, and split-chunk heuristics. Thirty-plus configuration categories. Two hundred lines before the first line of application code is processed.
The Webpack documentation, to its credit, is comprehensive. It has to be. The surface area of what can go wrong is so vast that the documentation is less a guide and more a survival manual. One does not learn Webpack configuration. One inherits it, from a colleague who has since left the company, in a file that has not been touched in fourteen months because the last person who touched it spent two days fixing the cascade of errors that followed.
The most common Webpack configuration strategy: copy it from Stack Overflow and pray.
The configuration file becomes load-bearing archaeology. Every module.rules
entry has a story. Every resolve.alias was a workaround for something.
Every plugin was added to fix a problem caused by another plugin. The configuration
does not describe a build process. It describes the accumulated anxieties of every
developer who has touched the project.
The Sentiment Index
Numbers measure performance. Surveys measure pain.
The State of JavaScript 2024 survey paints a portrait of a tool that the industry uses out of inertia rather than enthusiasm. Webpack’s usage stands at 86%, an enormous installed base. Its satisfaction score: 14% positive. Its dislike ratio: 37%. More than a third of its users actively dislike it. Only 14% would recommend it.
Vite, by contrast, reports a 98% retention rate. Ninety-eight per cent of developers who try Vite continue to use it. One does not typically see retention figures that high outside of subscription services that make cancellation deliberately difficult.
The gap between Webpack’s usage and its satisfaction is the gap between habit and choice. Eighty-six per cent of developers use Webpack because their project already uses Webpack, because the CI pipeline expects Webpack, because migrating away from Webpack requires touching the configuration file, and nobody wants to touch the configuration file. Fourteen per cent would choose it again. The rest are hostages.
The Problem That Solved Itself
Webpack was built to solve a genuine problem: browsers could not understand JavaScript modules. In 2012, if you wanted to split your code across multiple files, you needed a tool to reassemble them into something the browser could execute. Webpack did this. It did it well. It earned its place.
Then the platform caught up.
ES Modules shipped in Chrome 61 (September 2017), Firefox 60 (May 2018), Safari 11
(September 2017), and Edge 16 (October 2017). The <script type="module">
attribute told the browser to treat the file as a module. import and
export worked natively. No bundler. No loader. No configuration file.
The browser understood modules because the specification said it should, and the
browser vendors implemented the specification.
That was nine years ago. The problem Webpack solves has been solved, by the platform, natively, for nine years. And yet Webpack persists, not because the problem returned, but because the ecosystem built on top of the solution never noticed the problem had left.
The Invoice
Let us itemise.
106x slower than esbuild on Three.js. 167x slower on TypeScript compilation. 3.8 GB of RAM for a project that Webpack 4 handled in 800 MB. 30 GB in GitLab’s dev environment. Cold starts 3.3x slower than Vite. HMR 50 to 80 times slower. A configuration system with thirty-plus categories that no single developer fully understands. An 86% usage rate with a 14% satisfaction score.
Every one of these costs is documented. Every one is measurable. Every one is paid daily: in developer time waiting for builds, in CI minutes burning compute, in RAM allocated to a tool that concatenates files with the resource appetite of a database server.
Webpack was the right tool for 2012. It is the inherited tool of 2026. The distinction between those two is the Webpack Tax: the cost of continuing to pay for a problem the platform solved nine years ago, because the configuration file is too frightening to replace.