Shaking Off the Dead Code: How Tree Shaking Optimizes Your JavaScript Bundle
Neeraj Swarnkar
Sr. Staff Engineer - Full Stack / Front End at Eagleview | Ex-Cisco | Ex-HP | Trainer | React, Angular, Svelte, Node, Typescript, Javascript
Imagine dragging around a heavy toolbox filled with tools you never use.
That's what bloated JavaScript bundles feel like!
Introduction
In today's fast-paced web development landscape, optimizing code for performance is crucial. One of the most effective techniques for reducing bundle size and improving performance is tree shaking. This article explores what tree shaking is, its significance in JavaScript development, and how developers can leverage tools like Webpack and Rollup to implement it efficiently.
What is Tree Shaking?
Consequences of large bundles: slow loading times, poor user experience, and wasted resources.
Smaller and more efficient bundles. that's all.
At its core, tree shaking is a mechanism designed to prune unused or dead code from JavaScript bundles. By analyzing the code's dependency graph, tree shaking identifies and eliminates redundant pieces, resulting in leaner and more efficient bundles.
The Importance of Tree Shaking
In the digital realm where every millisecond counts, optimizing code for performance is paramount. Smaller bundle sizes achieved through tree shaking lead to quicker load times, a more responsive user experience, and even improvements in search engine rankings due to faster rendering.
Real-World Examples
Example
Let's say you have a JavaScript file with various functions, but you only use a few of them.
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
If you import math.js into another file and only use the add function:
// main.js
import { add } from './math.js';
console.log(add(2, 3)); // Output: 5
JavaScript file 'math.js' contains multiple functions, but only 'add' is imported and used in another file.
During the build process, a tool like webpack, when configured properly, performs tree shaking. It recognizes that subtract and multiply functions aren't used anywhere in the application, so it eliminates them from the final bundled code.
Example
Same principles apply to React components. When importing only specific components, tree shaking ensures that unused components do not bloat the final bundle, optimizing the application's performance.
In React, libraries like react-dom leverage tree shaking to remove unnecessary code. For instance, if you use react-dom to render components:
import { render } from 'react-dom';
// ...rendering components
Tree shaking helps remove unused functions or features from the react-dom library, resulting in a smaller bundle size when compiling the code.
So, in essence, tree shaking eliminates dead code by analyzing import and export statements to identify and remove any unused code paths, resulting in a more optimized and smaller bundle for your application.
Example
// function.js
export function sayHello() {
console.log("Hello!");
}
export function goodbye() {
console.log("Goodbye!");
}
// main.js
import { sayHello } from "./function.js";
sayHello(); // This function will be included in the bundle.
goodbye(); // This function will be removed by tree shaking as it's not used.
// Bundle includes only sayHello function and its dependencies.
Example
// MyComponent.js
import React from "react";
export default function MyComponent({ showButton }) {
if (showButton) {
return (
<div>
<p>My content...</p>
<button>Click me!</button>
</div>
);
} else {
return <p>My content without button...</p>;
}
}
// App.js
import React from "react";
import MyComponent from "./MyComponent";
function App() {
return (
<div>
<MyComponent showButton={true} />
<MyComponent showButton={false} />
</div>
);
}
// Bundle includes only the used parts of MyComponent depending on showButton prop.
Again, In the context of React, tree shaking can be seen with the import statement for components or utilities. For instance:
// Button.js
export function Button() {
// ...Button implementation
}
export function SecondaryButton() {
// ...SecondaryButton implementation
}
Suppose you only import and use Button in another file:
// App.js
import { Button } from './Button.js';
// ...using Button component
During the bundling process, the SecondaryButton function, which wasn't imported or used, will be eliminated from the final bundled code. This optimizes the bundle size.
领英推荐
Note: These are just simplified examples. In a real application, you'll likely have more complex dependencies and conditional code. Remember to configure your bundler (e.g., Webpack) to enable tree shaking for optimal results.
By practicing writing modular code and using clear import/export statements, you can leverage tree shaking to significantly reduce your bundle size and improve your application's performance.
Implementing Tree Shaking with Webpack & rollup
Modular code, clear dependencies, proper bundler configuration.
Webpack, a popular module bundler, offers built-in support for tree shaking. Configuring Webpack to harness this power involves setting the mode to 'production'. This triggers the optimization process, efficiently pruning out unused code paths.
Consider this sample webpack.config.js
module.exports = {
mode: 'production',
// other webpack configurations...
};
Rollup, renowned for its efficiency in generating compact bundles, is a champion in aggressively eliminating dead code. Utilizing Rollup involves defining an input file and specifying the desired output format, such as ES modules.
Take a glance at a basic rollup.config.js showcasing tree shaking and generating optimized bundles:
import { terser } from 'rollup-plugin-terser';
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'es',
},
plugins: [
terser(),
// other plugins...
],
};
Plugins like terser() further optimize the bundle by minifying the code.
Bonus - Advance Skill
React Applications with Tree Shaking and Code Splitting
To enable tree shaking in a React, developers can use the import and export syntax provided by ECMAScript modules which we shared earlier.
avoid using require function
Code splitting is an optimization technique utilized to enhance the performance and reduce the size of React applications. Unlike bundling the entire application code into a single file, code splitting enables developers to divide the application into smaller, manageable chunks that can be loaded selectively as required.
Dynamic Imports with React.lazy()
React introduces a dynamic import syntax provided by ECMAScript, enabling code splitting effortlessly. Using React.lazy() along with the import() function, developers can dynamically load modules or components when they are needed, rather than loading them upfront during the initial application load.
const MyModule = React.lazy(() => import('./MyModule'));
This syntax allows the module to be loaded only when it is needed, improving the initial loading time of the application and reducing its overall size.
Maximizing Angular Performance with Tree Shaking
Angular also provides built-in support for tree shaking through the use of @angular-devkit/build-optimizer package.
Need to add flag to the ng build or ng serve command.
Example
ng build --prod --build-optimizer
This package includes a build optimizer that performs tree shaking and other optimizations during the build.
However, if you want to disable the Build Optimizer for some reason, you can do so by using the --build-optimizer=false flag:
ng build --prod --build-optimizer=false
Build Optimizer is a helpful tool provided by Angular to optimize the generated bundles, making your application smaller and faster.
Additional resources
Closing Thoughts
Join the optimization journey!
Let's elevate our coding practices together for a faster and more efficient web.
#javascript #react #webdev #performance #treeshaking #angular #webpack #rollup
Senior Software Developer at Itron (SAFe 4 Agile Software Certified )
1 年Thanks for sharing. Good Article
Amazing????
Associate @ PWC India || Ex Infosys || FullStack developer || Mean stack developer || Mern stack developer || Frontend developer
1 年Thanks for posting ??
Product Architect @ phando.com | Video Streaming | OTT | E-learning | LMS | Epaper | EdTech | eCommerce | Application Security | Web Development | Scrum | Agile | Product Management
1 年Very useful Neeraj Swarnkar