← Back to Articles         
How do you reduce the Angular bundle size?

How do you reduce the Angular bundle size?

Published on 02 Oct 2026     10 min read Angular
Performance

How Do You Reduce Angular Bundle Size?

What is Angular Bundle Size?

When you build an Angular application, Angular's build tooling packages your application code and dependencies into JavaScript and other assets that the browser downloads.

For example:

Angular Source Code
       +
Angular Libraries
       +
Third-Party Packages
       ↓
      Build
       ↓
JavaScript / CSS / Assets
       ↓
Browser downloads them

If the initial bundle is too large, the browser has more JavaScript to:

Download
   ↓
Parse
   ↓
Compile
   ↓
Execute

This can increase startup time, especially on slower networks and devices.

The main goal is therefore:

Keep the initial bundle small and load non-critical code only when it is needed.


Full Simple Sample

One of the most effective techniques is lazy loading.

app.routes.ts

import { Routes } from '@angular/router';

export const routes: Routes = [
  {
    path: '',
    loadComponent: () =>
      import('./home/home')
        .then(m => m.Home)
  },
  {
    path: 'products',
    loadComponent: () =>
      import('./products/products')
        .then(m => m.Products)
  },
  {
    path: 'reports',
    loadComponent: () =>
      import('./reports/reports')
        .then(m => m.Reports)
  },
  {
    path: 'admin',
    loadChildren: () =>
      import('./admin/admin.routes')
        .then(m => m.ADMIN_ROUTES)
  }
];

home/home.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  standalone: true,
  template: `
    <h2>Home</h2>
    <p>Welcome to the application.</p>
  `
})
export class Home {
}

products/products.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-products',
  standalone: true,
  template: `
    <h2>Products</h2>
    <p>Products loaded.</p>
  `
})
export class Products {
}

reports/reports.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-reports',
  standalone: true,
  template: `
    <h2>Reports</h2>
    <p>Reports loaded.</p>
  `
})
export class Reports {
}

admin/admin.routes.ts

import { Routes } from '@angular/router';

export const ADMIN_ROUTES: Routes = [
  {
    path: '',
    loadComponent: () =>
      import('./dashboard')
        .then(m => m.Dashboard)
  }
];

How Does This Reduce Bundle Size?

Without lazy loading, imagine the application needs:

Home       100 KB
Products   300 KB
Reports    500 KB
Admin      400 KB
-----------------
Total     1300 KB

If everything is eagerly included in the startup path:

Application starts
       ↓
Download a large amount of code
       ↓
Parse
       ↓
Execute
       ↓
Application ready

With lazy loading:

Initial application
       ↓
Home + shared/core code

User opens Products
       ↓
Products chunk downloaded

User opens Reports
       ↓
Reports chunk downloaded

So the initial payload can be much smaller.


Important Ways to Reduce Angular Bundle Size

1. Use Lazy Loading

This is one of the most important techniques.

Instead of eagerly importing a feature:

import { Reports } from './reports/reports';

use:

{
  path: 'reports',
  loadComponent: () =>
    import('./reports/reports')
      .then(m => m.Reports)
}

This enables code splitting.

Before

main.js
████████████████████████████


After

main.js
████████

products chunk
████

reports chunk
██████

admin chunk
█████

The browser doesn't need every chunk immediately.


2. Use @defer for Heavy Components

Suppose your dashboard contains:

Header
Summary
Statistics
Large Chart
Comments
Recommendations

The chart may require a large charting library.

You can defer it:

<h1>Dashboard</h1>

<app-summary />

@defer (on viewport) {

  <app-sales-chart />

} @placeholder {

  <p>Chart will load when needed...</p>

}

Flow:

Dashboard starts
       ↓
Critical content loads
       ↓
Chart not required yet
       ↓
User scrolls toward chart
       ↓
Chart code loaded

This can keep heavy dependencies out of the initial loading path.


3. Avoid Large Third-Party Libraries

Before installing a package, ask:

Do I actually need this library?
        ↓
How large is it?
        ↓
Is it tree-shakable?
        ↓
Is there a smaller alternative?
        ↓
Can Angular/browser APIs already do this?

For example, don't add a very large utility library just to perform one simple operation that JavaScript already supports.

Instead of depending on a library for basic array operations:

const activeUsers =
  users.filter(user => user.isActive);

native JavaScript may be sufficient.


4. Import Only What You Need

Avoid unnecessarily broad imports where a library supports granular imports.

Conceptually, avoid:

import * as HugeLibrary from 'huge-library';

when you only need one utility and the package provides a tree-shakable/granular entry point.

Prefer something like:

import { requiredFunction } from 'library/specific-entry';

Important: the exact benefit depends on how that particular package is packaged and whether it supports tree shaking.


5. Tree Shaking

Tree shaking removes code that isn't actually used by the application, when the code and dependencies are structured in a tree-shakable way.

Suppose a library provides:

Function A
Function B
Function C
Function D
Function E

Your application only uses:

Function A

With effective tree shaking:

A → retained

B → removed
C → removed
D → removed
E → removed

This reduces production output.


6. Use Production Builds

Development builds prioritize debugging and developer experience.

For deployment, use the production configuration:

ng build --configuration production

Production builds apply optimizations such as:

  • Minification
  • Tree shaking/dead-code removal
  • Build optimizations
  • Optimized output/chunking

Conceptually:

Development Code

function calculateProductPrice(product) {
    const price = product.price;
    return price;
}

may be transformed into more compact production JavaScript.

You generally shouldn't judge final bundle size from a development build.


7. Remove Unused Dependencies

Over time, projects often accumulate packages.

Check your:

package.json

You may find packages that were installed for experiments but are no longer used.

For example:

{
  "dependencies": {
    "some-old-library": "...",
    "unused-chart-library": "...",
    "another-unused-package": "..."
  }
}

If they are truly unused, remove them.

npm uninstall unused-package

However, merely appearing in package.json doesn't automatically mean the package is included in your browser bundle. The important issue is whether it is imported/reachable from application code.


8. Avoid Importing Server-Only or Node-Oriented Libraries into Browser Code

Angular browser applications should avoid unnecessarily importing packages designed primarily for Node/server environments.

For example, don't pull a heavy server-oriented dependency into frontend code when a browser-native API can solve the problem.

This can cause:

  • Larger bundles
  • Compatibility problems
  • Polyfill requirements

9. Optimize Angular Feature Imports

Standalone Angular makes dependencies explicit at component level.

For example:

@Component({
  standalone: true,
  imports: [
    RouterLink
  ]
})

Instead of importing unrelated functionality that the component doesn't need.

Similarly, if a component only needs reactive forms:

imports: [
  ReactiveFormsModule
]

don't add unrelated modules just because another screen uses them.


10. Keep Heavy Features Lazy

Suppose your application has:

Public Site
Admin
Reports
Charts
PDF Viewer
Rich Text Editor
Analytics

Some of these may depend on large libraries.

A useful architecture is:

Initial Bundle
│
├── App shell
├── Home
└── Essential shared code


Lazy Chunks
│
├── Admin
├── Reports
├── Charts
├── PDF Viewer
└── Rich Text Editor

For example, your TinyMCE-based article editor is an excellent example of functionality that generally does not need to be part of the initial public-site loading path.

The public visitor reading an article doesn't need to download admin editor functionality.


11. Optimize Images — But Understand the Difference

Images affect page weight, but they aren't normally part of your JavaScript bundle in the same sense as application code.

For example:

JavaScript bundle → 500 KB
Images            → 5 MB

Even if your JS bundle is small, the site can still load slowly because of images.

So optimize:

  • Image dimensions
  • Compression
  • Modern formats
  • Lazy loading
  • Angular NgOptimizedImage

Example:

<img
  ngSrc="/images/product.webp"
  width="400"
  height="300"
  alt="Product">

This improves overall page performance even though it is technically a different optimization from reducing JavaScript bundle size.


12. Analyze the Bundle

Don't guess which dependency is making the application large.

Build the application and inspect the generated output:

ng build --configuration production

The build output reports generated files/chunks and sizes.

Look for unusually large chunks:

Initial chunks
--------------------------------
main           ...
polyfills      ...
styles         ...

Lazy chunks
--------------------------------
reports        ...
admin          ...
chart          ...

The key question is:

What is inside my initial bundle, and does it actually need to be there?


13. Configure Bundle Budgets

Angular build configuration supports budgets that can warn or fail when bundle sizes exceed defined thresholds.

In angular.json, conceptually:

"budgets": [
  {
    "type": "initial",
    "maximumWarning": "500kB",
    "maximumError": "1MB"
  }
]

This helps prevent bundle size from silently growing over time.

For example:

Developer adds large library
        ↓
Initial bundle grows
        ↓
Budget threshold exceeded
        ↓
Build warning/error
        ↓
Team investigates

This is particularly useful in CI/CD.


14. Be Careful with Shared Code

Suppose you create:

shared/

and put everything inside it:

Shared
├── Buttons
├── Charts
├── PDF
├── Editor
├── Reports
├── Utility functions
└── Admin components

Then many features broadly import that shared entry point.

You may accidentally make heavy dependencies reachable from places that don't need them.

Keep shared code focused and structure imports so heavy feature-specific dependencies stay inside their feature boundaries.


15. Lazy Load Feature Areas

For larger applications, organize by features.

src/app
│
├── home
├── products
├── articles
├── admin
│   ├── dashboard
│   ├── articles
│   ├── categories
│   └── tags
└── shared

Then:

{
  path: 'admin',
  loadChildren: () =>
    import('./admin/admin.routes')
      .then(m => m.ADMIN_ROUTES)
}

This makes it easier to keep the entire admin feature outside the public application's initial bundle.

For an Angular frontend serving both your public portfolio and admin area, this separation is particularly valuable.


Bundle Size vs Application Performance

Don't confuse these concepts.

A smaller bundle primarily helps:

Network download
      +
JavaScript parsing
      +
Compilation/execution
      ↓
Startup performance

But runtime performance involves other concerns:

Change detection
DOM size
Large lists
Expensive calculations
Memory
Frequent events
API calls

Therefore:

Lazy Loading
@defer
Tree Shaking
Dependency Optimization
        ↓
Bundle / Startup Optimization

while:

OnPush
Signals
track
Virtual Scrolling
        ↓
Runtime / Rendering Optimization

Both matter.


Most Important Techniques

For interview preparation, remember these 8:

1. Lazy load routes/features
2. Use @defer for heavy non-critical components
3. Remove unnecessary third-party libraries
4. Import only required functionality
5. Ensure dependencies are tree-shakable
6. Use optimized production builds
7. Analyze generated chunks
8. Configure bundle-size budgets

Key Points

  • Bundle size determines how much application JavaScript the browser must initially download and process.
  • Lazy loading is one of the most important techniques for reducing initial bundle size.
  • loadComponent() lazy-loads standalone components.
  • loadChildren() lazy-loads feature route groups.
  • @defer can keep heavy UI dependencies out of the initial loading path.
  • Avoid unnecessary or oversized third-party packages.
  • Tree shaking removes unreachable/unused code when dependencies support it.
  • Use production builds when measuring deployable bundle size.
  • Remove unused dependencies and unnecessary imports.
  • Configure bundle budgets to prevent bundle-size regressions.
  • Measure before optimizing.

Interview Questions and Answers

1. How do you reduce Angular bundle size?

Use lazy loading, @defer, tree-shakable dependencies, production builds, granular imports, removal of unused/large libraries, bundle analysis, and bundle budgets.

2. How does lazy loading reduce bundle size?

It keeps feature code out of the initial bundle and loads that code in separate chunks when the feature is needed.

{
  path: 'reports',
  loadComponent: () =>
    import('./reports')
      .then(m => m.Reports)
}

3. What is tree shaking?

Tree shaking removes code that isn't reachable/used by the application from optimized production output, provided the code and dependencies support it.

4. How does @defer help?

@defer (on viewport) {
  <app-chart />
}

It can defer the code and dependencies associated with non-critical UI until the configured trigger occurs.

5. Why should we avoid large third-party libraries?

They can significantly increase JavaScript bundle size, increasing download, parsing, and execution costs.

6. Does OnPush reduce bundle size?

Not significantly.

ChangeDetectionStrategy.OnPush

primarily improves runtime change-detection behavior, not JavaScript bundle size.

7. Do Signals reduce bundle size?

Signals are primarily a reactivity/runtime architecture feature. Their main purpose isn't bundle-size reduction.

8. Does track reduce bundle size?

No.

@for (product of products; track product.id)

primarily improves list reconciliation and DOM reuse.

9. How do you prevent the bundle from becoming too large?

Configure Angular bundle budgets so builds produce warnings or errors when defined size thresholds are exceeded.

10. What is the best interview answer?

I reduce Angular bundle size by lazy-loading routes and feature areas, using @defer for heavy non-critical components, avoiding unnecessary third-party libraries, using tree-shakable and granular imports, removing unused dependencies, building with production optimizations, analyzing generated chunks, and enforcing bundle-size budgets. The main objective is to minimize the JavaScript required for the initial application load.

← Back to Articles