Optimizing Webpack build performance
I’m going to share the results of reducing Webpack build time for a particular frontend application. Application is based on TypeScript and React. In numbers we had:
- 352 .tsx files, 96k SLOC
- 22 css/scss files
- one output bundles, 6.8Mb unuglified with sourcemaps.
Initial configuration of the build:
- webpack v2.2.1
- babel-loader + ts-loader for .tsx files
- commons-chunk plugin for extracting vendor dependencies to a separate bundle
- webpack devtool=eval-source-map.
Before optimization our build took:
- 23s full build
- 13s incremental build (a simple change in a module with a small number of incoming dependencies).
Here is the list of improvements we have implemented and their effect on the incremental build time:
- replace ts-loader with awesome-typescript-loader (ATSL) -5s
- ATSL useCache=true -4s
- webpack unsafeCache=true -0.2s
- devtool=cheap-module-eval-source-map -0.5s
- pack vendor dependencies using DllReferencePlugin -0.5s (effect is significant for the initial build).
These improvements reduced incremental build time to around 3s but that was still too much. So I have decided to drop type checking for the development and leave it only for the CI builds:
- ATSL option transpileOnly -2s.
That resulted in ~1s for incremental build which appeared to be ok for us.
Besides these improvements following tweaks improved build time but were not implemented due to different issues:
- multiStep mode for Hot Module Replacement. Most promising one but seems to trigger additional reload, also lacks documentation
- replace ATSL with custom script to watch and transpile .tsx files. Improves build time from 1s to 0.7s or even to 0.6s with happy-pack. But complicates development environment setup.
- PrefetchPlugin. Effect is not clear, lacks documentation
- replace HtmlWebpackPlugin with static html file.
In addition, things I have tried that didn’t improve build time:
- use babel with ATSL
- ATSL CheckerPlugin
- downgrade css-loader to 0.14
- ATSL forkChecker=true
- happy-pack with ATSL (didn’t work at all)
- isolatedModules + noResolve TS options make things worse with ATSL.
In case any one is interested I’m going to share custom script for watching and transpiling .tsx as TypeScript/React/Webpack starter kit on GitHub. Please share you comments on that.
May your builds be ultra-fast!