Webpack Rebuild Improvement: How A One Line Change Yielded A 93% Increase — CB Insights Research

Yunfei Yan
CBI Engineering
Published in
3 min readFeb 13, 2020
Photo by Bill Jelen on Unsplash

As our product features have evolved, so has our codebase. Here is our approach to shortening build times.

Here at CB Insights, we’ve developed our web application using a modern tech stack that was built using React, Redux, Node.js, and Webpack as a bundling tool. The Webpack dev server and its hot-reload have enabled a fast development environment and the ability to execute quickly.

But as our product features have evolved, our codebase has naturally evolved with it.

This has led to an increase in our Webpack rebuild times, which has had a negative impact on our workflow. At times, we’ve waited more than 30 seconds for a one line change. Now, imagine that 30 seconds multiplied by the number of frontend developers, and you can understand why we found it counterproductive.

Below, we dive into our approach to solving this problem.

Measuring the problem

Thankfully, the webpack CLI provides tooling right out of the box to profile and measure each individual plugin.

Using webpack’s progress profile, we were able to see how long each step took. See the screenshot to the right to see our sample output.

For this rebuild, the total rebuild time was 35175ms, but what’s really interesting is that there are only a few slow steps (outlined below) relative to the rest:

  • Chunk graph took 9338ms
  • Basic chunk optimization took 23164ms
  • Advanced chunk optimization took 1085ms

Altogether, these 3 steps took 33587ms, which accounts for 95.49% of the total rebuild time.

So, how do we fix this?

After doing some research, we found this solution here: babel-plugin-dynamic-import-node .

TL;DR: it is replacing the import statements with requires. As any good engineering organization should do, we wanted to better understand what this was actually doing, so we read through the documentation and source code.

Require vs Import

To understand the problem better, we needed to know the differences between require and import for the Webpack build.

  1. Require: bring all required modules into one chunk. This is not good for performance and chunk size. But Webpack builds it fast due to the “all in one” structure.
  2. Import: dynamic import will generate its own chunks. It is better for app performance — but to generate, map, and optimize those chunks are heavy operations for Webpack build.

When we tested on one of our projects, build with require only got 3 chunks, but using import yielded 100+ chunks.

Build with require:

Build with import:

Now having discovered the issue, we want good performance on product and fast build time on development. But we need to solve the dilemma of require being the solution for optimizing building time while import being the solution for optimizing production performance.

How we do that?

As mentioned above, So simply applying it to a development environment will fix the issue. this babel-plugin (babel-plugin-dynamic-import-node) only does one thing — transform import to require.

Here are the rebuild details after the change (to the right).

Compared with the previous build:

  • Chunk graph 9338ms -> 193ms
  • Basic chunk optimization 23164ms -> 4ms
  • Advanced chunk optimization 1085ms -> 193ms
  • Total building time 35175ms -> 2353ms

The building time was reduced by 93%. While this is just a start, there is still room to optimize.

Originally published at https://www.cbinsights.com.

--

--