How to reduce webpack build time by 41.5% with this one weird trick
Tags: webpack, performance, build, rails
Published: 2020-08-05 14:43:29


# Webpack
Is a really good and extremely flexible tool. How many devs can confidently say they've built something that supports 99.999999% of user's use-cases?
It's certainly possible in theory, a naive implementation would be to just pass an "option" parameter and start going wild with the ifs statements. Now, imagine your option parameter having 1000 attributes, interacting with one another, in an unholy permutation of possibilities. I certainly wouldn't be able to build something remotely maintainable, even if I had the perfect specs beforehand and infinite time. And what about the plugin architecture, that allows expansion of webpack capabilities to suit even more those weird use-cases? Pretty sweet 👌

But, sadly, everything comes with a cost. Cognitive load for us simpletons who just want to transform our assets.

After becoming one with webapack docs (after so many reads and re-reads hehe), It feels I'm still just scratching the surface. I mean, there are so many moving parts (at least there was, I think they are doing an awesome job making the essential work out of the box) it's super easy to mess things up, especially if you didn't come from something magic like create-react-app or maybe you did come but had to eject and do some tweaks to support your use-case. It all starts with a library asking to add a custom loader to style their components, then It's typescript and the usage of ultra-modern javascript with babel, then just a quick transform to remove that unused prop for that specific build, optimize a little bit of CSS here and there, and suddenly even your config needs testing.

Now, if you have an unorthodox config and are struggling to improve your build time, let's talk about it.

You probably visited the [docs guide to perfomance](https://webpack.js.org/guides/build-performance/) (and if you don't speak webpack, you got quite lost, like me 🙃),  [Slack guide to webpack perfomance](https://slack.engineering/keep-webpack-fast-a-field-guide-for-better-build-performance-f56a5995e8f1), [Onfido guide to perfomance](https://medium.com/onfido-tech/speed-up-webpack-ff53c494b89c), and both linking to other infinite resources. You also probably tried measuring things with tools like the [speed-measure-plugin](https://github.com/stephencookdev/speed-measure-webpack-plugin), analyzed the results, removed some plugins, changed other configurations, measured again, added another plugin promising that parallelization would save the day, and ended yet another day frustrated, feeling beat by your own creation.

## The battle
Oh my god, I swear, the amount of effort both me and my dear friend put trying to understand the bottlenecks was immense... Maybe we didn't have the best methodology for debugging webpack, but still... Those are some precious memory I can't forget, me and him trying to make sense of our build together. :P

Here is a brief piece of that history.

Measuring first before tweaking performance is a must, and since all resources pointed to a common tool, we decided to give it a shot. Speed measure plugin gave the following scenario:

### Plugin metrics

![Plugin metrics](https://dev-to-uploads.s3.amazonaws.com/i/8iqbxjr3huzl84rgoxnt.png)

A quite bloody scenario, with ~12 minutes total. But wait... something is weird here. Looking just at the plugins metrics, how can "CaseSensitivePathsPlugin" be responsible for 5min of our build? A plugin responsible for just ensuring the case sensitivity of my files? Something seems really wrong, and before even looking to the rest of the metrics, we decided to tackle it by simply removing it.

![Result](https://dev-to-uploads.s3.amazonaws.com/i/z6xw8mx40h0ttngg4ekv.png)

COOL! We already managed to reduce 5 min of our build time! But we actually didn't. Overall output still took the 11 minutes 🙃 We didn't fully understand what happened, so to unblock ourselves we just ignored this result and continued to investigate.

### Loader metrics


![Loader metrics 1](https://dev-to-uploads.s3.amazonaws.com/i/74yl2zsq9ffcru8mmzwf.png)
![Loader metrics 2](https://dev-to-uploads.s3.amazonaws.com/i/baoq40d0mtumt75m6re4.png)

The loaders metrics didn't give much more insight either. Babel-loader was taking 9min to build. Well, with 5.6k TS/JS modules of course it would make babel sweat a little bit, so we just assumed there was nothing much we could do. Next, would be the sass preprocessor chain. 6min for just 103 files seems a little too much. Expose loader is weird, I just want my jquery to be globally available, why it's taking 3 minutes? Hmm they did look good suspects of our crime... but they were not.

We did tweak with both of them and achieved some kind of optimization... But not the optimization we were looking for.

Quite sometime later, we discovered that the ruby [slim](http://slim-lang.com/) preprocessor was quite under performant.   Maybe using a better implementation (perhaps rewritten in GO 👀) of it would lower the time......... OR MAYBE WE COULD JUST PURGE IT FROM OUR CODEBASE.

## The trick
We just gave up on slim and the result was like day and night. webpack-dev-server just went from a 5 min build to less than a minute. What about the production build? 730s → 427s, a 41.5 % improvement. BUT HOW?? wasn't slim only responsible for about 4min in our build time? Compared to Babel and Sass, it wasn't that much on the overall time... what was going on? Well, we measured things once again:
![Result 1](https://dev-to-uploads.s3.amazonaws.com/i/kqx3f0xwy6plqnkru000.png)
![Result 2](https://dev-to-uploads.s3.amazonaws.com/i/hy5ar80evfjthvll3ykm.png)


What? Really? Every metric went down? WTF?

Sorry, I really wanted to close this post by explaining what happened, but I can't.
Hopefully, some smart readers may help us solve this final mystery 🕵️‍♀️

## Conclusion
Every webpack config is super specific for each project, so every tweak for performance is super project-specific too. 

In the end, we traded the advantages of a modern html syntax like slim for a faster build and more pain to maintain our templates (like forgetting to close the damn div tag), but since 90% of those templates were just legacy code and were just slowing down the start of webpack-dev-server, the whole team was absolutely bought in when we reduced the local server build in 80%.


### Some resources
Some are a bit old, but I hope they help you in your journey!

[https://dev.to/sadarshannaiynar/demystifying-webpack-2f5n](https://dev.to/sadarshannaiynar/demystifying-webpack-2f5n)

[https://dev.to/slashgear_/how-to-boost-the-speed-of-your-webpack-build-16h0](https://dev.to/slashgear_/how-to-boost-the-speed-of-your-webpack-build-16h0)

[https://robertknight.me.uk/posts/webpack-dll-plugins/](https://robertknight.me.uk/posts/webpack-dll-plugins/)

[https://github.com/webpack/webpack/issues/1905](https://github.com/webpack/webpack/issues/1905)

[https://slack.engineering/keep-webpack-fast-a-field-guide-for-better-build-performance-f56a5995e8f1](https://slack.engineering/keep-webpack-fast-a-field-guide-for-better-build-performance-f56a5995e8f1)

[https://blog.box.com/how-we-improved-webpack-build-performance-95](https://blog.box.com/how-we-improved-webpack-build-performance-95)

[https://medium.com/onfido-tech/speed-up-webpack-ff53c494b89c](https://medium.com/onfido-tech/speed-up-webpack-ff53c494b89c)

[https://medium.com/ottofellercom/0-100-in-two-seconds-speed-up-webpack-465de691ed4a](https://medium.com/ottofellercom/0-100-in-two-seconds-speed-up-webpack-465de691ed4a)

[https://blog.logrocket.com/guide-performance-optimization-webpack/](https://blog.logrocket.com/guide-performance-optimization-webpack/)