Modern Frontend Optimization: A Deep Dive into Tree Shaking

Modern Frontend Optimization: A Deep Dive into Tree Shaking

Oct 4, 2019 · 4 min read · 654 Words · -Views -Comments

While Single Page Applications (SPAs) provide a fluid frontend experience, they introduce challenges like SEO optimization and ballooning bundle sizes. Fortunately, modern build tools offer solutions like Tree Shaking to prune unused code and optimize performance.

Tree Shaking Concept

What is Tree Shaking?

Tree shaking is a form of Dead Code Elimination (DCE). The term was popularized by the Rollup community and is now a core feature of Webpack. It refers to the process where the bundler “shakes” the dependency tree of your application to remove any modules or functions that are imported but never actually called.

Core Principles

  1. Static Analysis: Tree shaking relies on the static structure of ES2015 module syntax (import and export).
  2. ESM over CommonJS: Unlike require and module.exports (CommonJS), which are dynamic, ESM is static. This allows the compiler to determine what is used before the code actually runs.
  3. Pure Functions & Side Effects: Modern bundlers use the sideEffects property in package.json to identify which parts of a project are “pure” and safe to remove if unused.

Essential Tool: Webpack Bundle Analyzer

To optimize, you first need to measure. The webpack-bundle-analyzer plugin provides a visual treemap of your bundle, making it obvious which dependencies are taking up the most space.

Installation & Setup

  1. Install the plugin:

    npm install --save-dev webpack-bundle-analyzer
    
  2. Add a script to package.json:

    "scripts": {
      "analyze": "node scripts/build.js --analyzer"
    }
    
  3. Configure Webpack (webpack.config.prod.js):

    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    
    if (process.argv.includes('--analyzer')) {
        config.plugins.push(new BundleAnalyzerPlugin());
    }
    

Running npm run analyze will launch a local server (default port 8888) showing a detailed breakdown of your production bundle.


Practical Example: Project Code & Third-Party Libraries

Let’s look at how tree shaking works in a real-world project built with create-react-app.

1. Project Source Code

Imagine you have a utility file utils.js:

// utils.js
export const appendSuffix = str => str + '_suffix';
export const appendPrefix = str => 'prefix_' + str;

If your application only imports appendPrefix, a standard production build will identify that appendSuffix is never called. Thanks to Webpack’s mode: 'production', which enables the TerserPlugin by default, appendSuffix will be completely removed from the final bundle.

2. Trimming Third-Party Libraries (Lodash)

The standard lodash package uses CommonJS, which is famously difficult to tree-shake. If you import one function, you often end up with the entire library.

The Solution: lodash-es By switching to the ESM version of Lodash, you enable the bundler to pick only what you use.

# Replace lodash with lodash-es
npm uninstall lodash
npm install lodash-es
// Standard (Bad for tree shaking)
import _ from 'lodash'; 

// Optimized (Good for tree shaking)
import { map } from 'lodash-es';

3. Optimizing UI Frameworks (Ant Design)

UI libraries like Ant Design are massive. To avoid importing the entire library, use babel-plugin-import.

  1. Install the plugin:

    npm install babel-plugin-import --save-dev
    
  2. Configure .babelrc:

    {
      "plugins": [
        ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
      ]
    }
    

This configuration ensures that when you write import { Button } from 'antd';, only the Button component and its associated CSS are bundled.


Understanding Side Effects

A “side effect” occurs when a module does something other than just exporting values—for example, modifying a global variable or adding a polyfill to the window object.

If Webpack encounters a module with potential side effects, it won’t remove it, even if you don’t use any of its exports. You can hint to Webpack that your code is “pure” by adding this to your package.json:

{
  "name": "my-project",
  "sideEffects": false
}

If some of your files do have side effects (like CSS imports), list them explicitly:

"sideEffects": ["*.css", "./src/polyfills.js"]

Final Thoughts

Tree shaking is a powerful tool, but it’s not magic. It requires you to write modern, static ES6 code and carefully choose your third-party dependencies. By auditing your bundle regularly and using ESM-ready libraries, you can keep your frontend applications fast and lightweight.

References

Authors
Developer, digital product enthusiast, tinkerer, sharer, open source lover