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!