Published
- 5 min read
How to reduce bundle size in React, Vue, or Angular

We’ve all been there: you click a link, and then you wait. And wait. A slow-loading website is frustrating, and often, the culprit is a massive JavaScript bundle. The browser has to download, parse, and execute all that code before your user sees anything meaningful.
Think of it like packing for a weekend trip. You wouldn’t bring your entire wardrobe, right? You’d pack only what you need. A large JS bundle is like packing everything you own—it’s heavy, slow, and much of it is unnecessary for the initial page load.
In this guide, we’ll look at practical ways to pack smarter. We’ll cover universal principles and show you how to apply them specifically in React, Vue, and Angular to make your applications faster.
First, See What You’re Dealing With
You can’t optimize what you can’t measure. Before you start changing code, you need to know what’s taking up all the space. This is where a bundle analyzer is invaluable.
Most modern projects use a bundler like Webpack or Vite. These tools have plugins that create a visual map of your bundle, showing exactly which libraries and components are the heaviest. For Webpack, the most popular choice is webpack-bundle-analyzer
.
After configuring it, you can run a command that opens a treemap in your browser. This map makes it obvious if a single library is responsible for 30% of your bundle size. Now you have a clear target.
Implement Code Splitting and Lazy Loading
By default, your bundler creates one large JavaScript file containing all your app’s code. Code splitting is the technique of breaking that file into smaller chunks. Lazy loading is how you load those chunks only when they are needed.
Imagine you’re reading an encyclopedia. You wouldn’t read it cover to cover; you’d just jump to the entry you need. That’s what lazy loading does for your app’s features.
In React
React makes this straightforward with React.lazy
and Suspense
. You can wrap any component to load it dynamically.
import React, { Suspense, lazy } from "react";
// Lazily import the component
const UserProfile = lazy(() => import("./components/UserProfile"));
function App() {
return (
<div>
<h1>Welcome</h1>
{/* The UserProfile component will only load when it's needed */}
<Suspense fallback={<div>Loading profile...</div>}>
<UserProfile />
</Suspense>
</div>
);
}
In Vue
Vue uses dynamic import()
syntax for lazy loading components, which is often used with the Vue Router.
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{
path: "/dashboard",
name: "Dashboard",
// The component is only loaded when the user visits this route
component: () => import("@/views/DashboardView.vue"),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
In Angular
Angular’s router has built-in support for lazy loading entire modules. In your routing configuration, you use loadChildren
to point to a module file.
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
const routes: Routes = [
{
path: "admin",
// The AdminModule is only loaded when the /admin path is visited
loadChildren: () =>
import("./admin/admin.module").then((m) => m.AdminModule),
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Enable Effective Tree Shaking
Tree shaking is the process of removing unused code—or “dead code”—from your final bundle. Think of shaking a tree so only the ripe fruit falls off. Your bundler does the same, keeping only the code you actually use.
Most bundlers (like Webpack and Vite) enable this by default for production builds. However, you need to write your code in a way that allows it to work effectively. The key is to use ES6 module syntax (import
and export
).
For example, when importing from a library, only import what you need.
// Good: This allows the bundler to ignore the rest of the library
import { debounce } from "lodash-es";
// Bad: This forces the bundler to include the entire library
import _ from "lodash";
This principle applies equally to React, Vue, and Angular projects. Using component libraries that support direct imports (e.g., import Button from 'library/Button'
) is also crucial.
Be Smart About Your Dependencies
Your node_modules
directory can quickly become bloated. A small utility package might bring in a dozen other dependencies, ballooning your bundle size.
Before you run npm install
, check the package’s size on a site like BundlePhobia. It shows you the minified and gzipped size and whether it supports tree shaking.
Often, you can find a smaller alternative. A classic example is swapping the large, legacy moment.js
library for a lighter, modern alternative like date-fns
or Day.js
. This one change can save hundreds of kilobytes.
Final Thoughts
Reducing your bundle size is not a one-time task but a continuous practice of good development hygiene. By regularly analyzing your bundle and applying these techniques, you ensure a faster, more pleasant experience for your users, regardless of the framework you choose.
To recap:
- Analyze your bundle to identify the largest modules.
- Use code splitting to break your app into smaller, on-demand chunks.
- Write tree-shakable code by using ES6 module imports correctly.
- Audit your dependencies and choose lightweight alternatives.
A smaller bundle means a faster website. It’s one of the most impactful optimizations you can make.