How to trim duplicates from your Webpack bundle?

How to trim duplicates from your Webpack bundle?

In my quest to optimize the client bundle, I stumbled upon an interesting in-house mechanism that the node package manager uses to keep the bundle leaner and also how webpack employs aliases to avoid duplicacy. Bloating bundles must be avoided by front-end developers because it slows down webpage performance and increases page load time.

How flattening works ?

Front-end developers have a plethora of open-source libraries to choose from the npm registries to begin developing the application.The package managers get the code from the internet and the webpack puts the code in the bundle.In an engineering team, teams would be owning features and developers would be using packages from npm to develop those.

let's say we have a directory structure as follows,

#Directory             #Resolved
Company-client            
-node-modules
 -colorChart
  -chart@^1.2.1.       chart@1.3.0
 -ganttChart
  -chart@^1.1.4.       chart@1.3.0
-dashboard
 -homepage.js
  -colorChart
-analytics
 -reports.js
  -ganttChart

As we know, the package manager looks into the package.json files, creates a dependency tree to resolve and install the dependencies. The package manager recursively resolves each dependency. In this example ^ sign tells npm to install the latest minor version within the current major version hence the resolved version for the chart package is 1.3.0

Here the package manager avoids installing the package twice and installing only once by using node resolve resolution algorithm and ingesting the code only once in the Webpack bundle and preventing the bloating. This mechanism is called flattening

Nuances in flattening

But sometimes, the semver compatible node modules are not flattened causing the webpack to ingest similar packages multiple times in bundle. So why did the package manager did not flatten the node modules? Did it fail to recognize similar packages?

To understand this we need to know what webpack does. The webpack starts from an entry file, traverses all the module imports recursively and creates dependency graphs and concatenates the code into one or more bundles.

The flattening might not happen because it depends on how npm has placed the package in the disk and how webpack has bundled.

#Directory             #Resolved
Company-client            
-node-modules
 -ganttChart
  -chart@^1.1.4.       chart@1.1.4
 -colorChart
  -chart@^1.2.1.       chart@1.2.1
-analytics
 -reports.js
  -ganttChart 
-dashboard
 -homepage.js
  -colorChart

The above example indicate how the resolution would have happened if flattening failed.

Webpack alias to the rescue

As a fallback, if the flattening didnt work as expected, we could use webpack aliases to prevent duplication of dependencies

// webpack.config.js
module.exports = {
  //...
  resolve: {
    alias:{
    'chart':path.resolve(__dirname, 'node_modules/chart/')
    }
  },
};

In the above configuration, we insist the webpack to resolve to the version mentioned in the alias, whenever it encounters the import statements the requires chart package.

Thats a wrap, for now, hope you got to know something new in the blog. See you again with an interesting blog.