Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

Code Splitting in Angular

Code splitting is a technique to split your application code into smaller chunks, which can be loaded on demand. This improves the initial load time and performance of your application. This guide covers various methods to implement code splitting in Angular.

Lazy Loading Modules

Lazy loading helps to load feature modules only when they are needed, reducing the initial bundle size:

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'about', loadChildren: () => import('./about/about.module').then(m => m.AboutModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Preloading Modules

Preloading modules can further improve performance by loading feature modules in the background after the application is bootstrapped:

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'about', loadChildren: () => import('./about/about.module').then(m => m.AboutModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Dynamic Imports

Use dynamic imports to load JavaScript modules on demand:

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  async loadComponent() {
    const { LazyComponent } = await import('./lazy/lazy.component');
    // Use LazyComponent as needed
  }
}

Custom Preloading Strategy

Create a custom preloading strategy to selectively preload modules:

// selective-preloading-strategy.service.ts
import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SelectivePreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, load: () => Observable): Observable {
    return route.data && route.data['preload'] ? load() : of(null);
  }
}

Use the custom preloading strategy in your routes:

// app-routing.module.ts
const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'about', loadChildren: () => import('./about/about.module').then(m => m.AboutModule), data: { preload: true } }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy: SelectivePreloadingStrategy })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Code Splitting with Webpack

Configure Webpack for advanced code splitting techniques:

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/main.ts',
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  }
};

Using Angular CLI Budgets

Configure Angular CLI budgets to enforce size limits on your bundles:

// angular.json
{
  ...
  "projects": {
    "my-app": {
      ...
      "architect": {
        "build": {
          ...
          "configurations": {
            "production": {
              ...
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        }
      }
    }
  }
}

Optimizing Third-Party Libraries

Only import the parts of third-party libraries that you need to reduce the bundle size:

// Import specific functions from lodash
import { debounce } from 'lodash-es';

debounce(() => {
  console.log('Debounced');
}, 500);

Analyze Bundle Size

Analyze your bundle size to identify and remove unused code. Use tools like source-map-explorer:

npm install source-map-explorer
ng build --prod --source-map
npx source-map-explorer dist/my-app/main.*.js

Key Points

  • Use lazy loading to load feature modules only when needed.
  • Preload modules in the background to improve performance.
  • Use dynamic imports to load JavaScript modules on demand.
  • Create a custom preloading strategy to selectively preload modules.
  • Configure Webpack for advanced code splitting techniques.
  • Configure Angular CLI budgets to enforce size limits on your bundles.
  • Import only the necessary parts of third-party libraries to reduce the bundle size.
  • Analyze your bundle size to identify and remove unused code.

Conclusion

Implementing code splitting in your Angular application helps to improve performance by reducing the initial load time. By using techniques such as lazy loading, preloading, dynamic imports, custom preloading strategies, and optimizing third-party libraries, you can efficiently manage the bundle size of your application. Happy coding!