How We Sped Up Our Webpack (TailwindCSS) Build By 74%
Tags: performance, webpack, tailwindcss
Published: 2021-03-22 10:23:55

Since Github Actions became a thing, I became interested in saving precious seconds in our plan by optimizing assets build time. As long as it didn't exceed 60 seconds, there was little motivation, but once it did, I said enough is enough.

Our build step runs two commands:

- `npm ci`
- `npm run build`

We use babel and TailwindCSS. Using simple methods, I discovered that CSS and JS take about the same time to build. 

> Benchmark: Webpack build took **64** seconds, whole build took **91** seconds.

## Replacing babel-loader + terser with [esbuild loader](https://github.com/privatenumber/esbuild-loader)

The first thing I did was replace `babel-loader` and Terser (minification tool) with [esbuild-loader](https://github.com/privatenumber/esbuild-loader). This made our JS compile around 12 times faster, it went down to 1.4 seconds. It was a good start.

> Result: Webpack build took **40** seconds (down from 64), whole build took **65** seconds.

## Configuring Tailwind

The second optimization had to do something with CSS because that's where most of the build time now lay. I visited the TailwindCSS documentation to find out how to decrease build size.

The template we base our projects on uses a style guide with predefined colors, sizes, etc., so we don't need some of the configuration from TailwindCSS. Knowing this, here's what I did:

1. Moved `colors` configuration outside `extend`, which disabled all the built-in colors from the build. This made a huge difference in development file size (10.5MB → 4MB).
2. Moved `spacing` configuration outside `extend`
3. Disabled corePlugins

I had to bring some of these back because we used them in a couple of places. After these changes, I considered TailwindCSS optimization done. 

The file size of development CSS went down from 10.5MB to 3.9MB, which is a big deal (depending on the developer's connection speed) if you are sending your CSS on every CSS change. It does not happen often when working with TailwindCSS, but it was still a welcome improvement for everyone using our `pos-cli sync` command.  

> Result: Webpack build took **26** seconds (down from 40), whole build took **49** seconds.

---

Read about TailwindCSS optimization in their documentation:

- [https://tailwindcss.com/docs/optimizing-for-production](https://tailwindcss.com/docs/optimizing-for-production)
- [https://tailwindcss.com/docs/configuration](https://tailwindcss.com/docs/configuration#theme)

## Disabling PostCSS processing

The last step was to disable PostCSS processing of CSS pulled in from `node_modules`.

Before, it was pretty naive — everything went through all the CSS loaders:

```yaml
{
  test: /(\.css)$/,
  use: [
    MiniCssExtractPlugin.loader,
    { loader: 'css-loader', options: { url: false } },
    'postcss-loader',
  ],
},
```

I split it into two so that `node_modules` are processed only by `css-loader`, and application CSS is processed by PostCSS first.

```yaml
{
  test: /(\.css)$/,
  include: /node_modules/,
  use: [
    MiniCssExtractPlugin.loader,
    { loader: 'css-loader', options: { url: false } }
  ],
},
{
  test: /(\.css)$/,
  exclude: /node_modules/,
  use: [
    MiniCssExtractPlugin.loader,
    { loader: 'css-loader', options: { url: false } },
    'postcss-loader',
  ],
},
```

> Result: Webpack build took **17** seconds (down from 26), whole build took **39** seconds.

### That's all :)

This journey was one of those creative ones where you fiddle around, find gains in various places, and they add up. In this case, they added up to 52 seconds of savings for every build. And we build a lot, so this improves our developer experience and lowers the cost of CI.

| Action                       | Webpack build time (seconds) | Whole build time (seconds) |
|------------------------------|------------------------------|----------------------------|
| At the start                 |              64              |             91             |
| Using esbuild loader         |              40              |             65             |
| Configuring Tailwind         |              26              |             49             |
| Disabling PostCSS processing |              17              |             39             |

In the following article, I will report how development speedup is going because the TailwindCSS team just released the experimental [TailwindCSS JIT](https://github.com/tailwindlabs/tailwindcss-jit), which might improve live development even further.

## Read more

If you are interested in more performance oriented content, follow me and I promise to deliver original, or at least effective methods of improving your website. 

{% link https://dev.to/platformos/platformos-documentation-site-webpack-setup-93l %}

{% link https://dev.to/platformos/3-performance-tips-for-your-next-project-2bdm %}

{% link https://dev.to/platformos/should-you-always-care-about-your-website-size-2jcc %}