build performance

Stephen Cook edited this page Apr 2, 2018 · 31 revisions

If you are looking to speed up webpack, you might be able to further improve the performance of your webpack build performance by following any number of the following tips and methods:

Incremental build

Make sure you don't do a full rebuild. Webpack has a great caching layer that allows you to keep already compiled modules in memory. There are some tools that help to use it:

Exclude modules from parsing

With noParse you can exclude big libraries from parsing, but this can break stuff.

Hints from build stats

There is an analyse tool which can perform a detailed analysis and provide useful information on how to optimize your build size and performance.

You can generate the required JSON file by running webpack --profile --json > stats.json


Generating the source file from internal representation is expensive. Each chunk is cached on its own, but only if nothing changes in this chunk. Most chunks only depend on the included modules, but the entry chunk is also considered as dirty if the additional chunk name changes. So by using [hash] or [chunkhash] in filenames the entry chunks need to be regenerated on (nearly) every change.

By using HMR the entry chunk need to embed the hash of the compilation and is also considered as dirty on every compilation.


Perfect SourceMaps are slow.

devtool: "source-map" cannot cache SourceMaps for modules and need to regenerate complete SourceMap for the chunk. It's something for production.

devtool: "eval-source-map" is really as good as devtool: "source-map", but can cache SourceMaps for modules. It's much faster for rebuilds.

devtool: "eval-cheap-module-source-map" offers SourceMaps that only maps lines (no column mappings) and are much faster.

devtool: "eval-cheap-source-map" is similar but doesn't generate SourceMaps for modules (i.e., jsx to js mappings).

devtool: "eval" has the best performance, but it only maps to compiled source code per module. In many cases this is good enough. (Hint: combine it with output.pathinfo: true.)

The UglifyJsPlugin uses SourceMaps to map errors to source code. And SourceMaps are slow. As you should only use this in production, this is fine. If your production build is really slow (or doesn't finish at all) you can disable it with new UglifyJsPlugin({ sourceMap: false }).


The UglifyJsPlugin introduced the parallel flag in its version 1. Using this flag can massively speed up your bundle!

If you are using webpack 1, 2, or 3's built-in UglifyJsPlugin, then consider not using the built-in plugin, and npm install UglifyJsPlugin manually, in order to upgrade to version 1 and get these additional speed benefits.

resolve.root vs resolve.modulesDirectories

Only use resolve.modulesDirectories for nested paths. Most paths should use resolve.root. This can give significant performance gains. See also this discussion.

Optimization plugins

Only use optimization plugins in production builds.

Prefetching modules


Dynamic linked library

If you have a bunch of rarely changing modules (i.e. vendor libs) and chunking doesn't give you enough performance (CommonsChunkPlugin), there are two plugins to create a bundle of these modules in a separate build step while still referencing these modules from the app bundle.

To create the DLL bundle beforehand you need to use the DllPlugin. Here is an example. This emits a public bundle and a private manifest file.

To use the DLL bundle from the app bundle you need to use the DllReferencePlugin. Here is an example. This stops following the dependency graph of your app when a module from the DLL bundle is found.

Optional loaders

Some loaders are not always necessary. For example, image-webpack-loader optimises images, and isn't actually needed in development - instead just file-loader can be used.


Caching methods like HardSourceWebpackPlugin and cache-loader are great for local development, and can cut off large amounts of time.

They also have an initial overhead, however. Dropping caching in your production config can save you this overhead.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.