DEV Community

Cover image for Web Dev Efficiency: Achieving Faster Builds and Lower Memory Load with Webpack
Sibelius Seraphini for Woovi

Posted on

Web Dev Efficiency: Achieving Faster Builds and Lower Memory Load with Webpack

We have been using Webpack forever (2015 to be exact).
We tried to move to vite, snowpack, esbuild, bun, turbopack, but none of them can bundle everything that we need to bundle yet, like our backends, frontends, widgets, plugins, and scripts.

As we can't leave Webpack, we found many ways to optimize it.
Making it faster and to consume fewer memory.

Making it fast and consuming less memory

The first thing you can do is to have different configurations for development and production.

We use webpack-merge to merge our common configurations that are the same for development and production.
We have the following structure

webpackCommonConfig.ts
webpackDevConfig.ts
webpackProdConfig.ts
Enter fullscreen mode Exit fullscreen mode

Source Map

We need to compile modern JavaScript code to be compatible with older browsers.
The source map does the mapping from the generated code to the source code. This is useful for debugging, development and error monitoring in production.
We can use a faster source map in development to speed up bundling.

devtool: 'cheap-module-source-map',

cheap-module-source-map provides the best cost benefit for source map in development.

Pathinfo

outputpathinfo

output: {
   pathinfo: false,
},
Enter fullscreen mode Exit fullscreen mode

pathinfo: false will output fewer comments in bundles making bundling faster.

Babel-loader vs esbuild-loader vs SWC-Loader

Deciding what loader will compile your TypeScript code can speed up bundling a lot.
Babel is the default one, but it is slow.
Esbuild and SWC are faster, but only SWC has a Relay plugin that we need.

So, we use swc-loader to compile our TypeScript code.

writeToDisk: true

devServer: {
   devMiddleware: {
      writeToDisk: true,
    },
}
Enter fullscreen mode Exit fullscreen mode

Webpack Dev Server will default to bundling everything in memory.
This is faster, but if you have a very big frontend as we have, it will consume a lot of memory.
One of our frontends was consuming more than 5GB of RAM, when we switched to writeToDisk: true, it started consuming fewer than 1GB of RAM.
We didn't notice any performance loss with this change.
The computer became even more responsive with less memory pressure.

Persistent cache

cache: {
    type: 'filesystem',
  },
Enter fullscreen mode Exit fullscreen mode

We opt-in Webpack persistent cache using the filesystem, to avoid consuming a lot of memory, and to also speed up rebuilds.
If we stop our Webpack bundling process and start it over, it will catch up from the last cache point.

Lazy Compilation

experiments: {
      lazyCompilation: {
        imports: true,
        entries: true,
      },
      cacheUnaffected: true,
    },
Enter fullscreen mode Exit fullscreen mode

Lazy Compilation will lazy bundle/compile entry points and dynamic imports.
This will make your bundle compile faster, and it will also use less memory as we need to bundle less.
Every page/route is a dynamic import, so it is lazily compiled at Woovi.
This makes sure we only compile the routes we are working on.

Key Takeaways

Every optimization was done over time.
We dig into documentation, issues, articles, and code to find the right configuration that fit better our use cases.
We also used memory and CPU profiles to find bottlenecks to focus our optimization efforts.

I do believe there is even more optimization to be done.

If you have even more Webpack or bundling tricks comment on the article.


Woovi
Woovi is a Startup that enables shoppers to pay as they like. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.

If you want to work with us, we are hiring!


Photo by Zoltan Tasi on Unsplash

Top comments (2)

Collapse
 
walesl04 profile image
Wale

Amazing post! Thank for shared!

I also like to use this pattern for webpack files:

webpack.common.js
webpack.config.js (env file for mode: production, stage or developement)
Enter fullscreen mode Exit fullscreen mode

for optimization, using splitChunks for dynamic routes in React/Vue.js mainly on my my micro-frontends :)

and for a better babel loader I use options cacheDirectory true.

Collapse
 
amenadiel profile image
Felipe Figueroa

As usual, dev.to posts providing concrete and insightful tips instead of generic nonsense. I love this kind of content.