Angular Tree Shaking Service

Piyali Das
4 min readNov 21, 2023

--

Tree shaking is a way to eliminate unused modules from the final bundle file of the application. The Angular CLI, by default, uses the Webpack bundler for bundling script files, which supports Tree Shaking from version 2.

Tree Shaking is a Process wherein the unused code is removed during the build phase.

Tree shaking — what is it?

One of the biggest problems with Angular is the size of the created application. Nowadays, the size of our application stands for the amount of JavaScript users have to download on their devices. The Angular development team was given a bundle size optimization goal.

Tree shaking is a step in a build process that removes unused code so the application becomes smaller. It can be visualized as shaking a physical tree causing dead branches and leaves to fall off.

One of the optimizations they used with the new Ivy rendering engine was the introduction of the tree shaking technique. Tree shaking, also called dead code elimination, is a process during which unused code is removed from our build. This technique allows us to reduce the final size of our application.

Tree shaking in Angular Ivy

The insertion of tree shaking to the new Ivy rendering engine was a big step towards application optimization. Now let’s explain how Angular recognizes code fragments which it doesn’t need. First, we need to understand what is the incremental DOM, on which the Ivy rendering engine is based.

Team Google decided to introduce Incremental DOM to achieve two goals:

  • Smaller bundle size
  • Reduce the RAM requirements of the rendering engine

Incremental DOM involves recompiling each component into a set of instructions. The instructions allow us to create a DOM tree and then update the parts with muted data. This approach allows us to get rid of the Angular interpreter from the final bundle. Additionally, the way the instructions are used to update the DOM requires less memory compared to the Virtual DOM used among others, by React, which generates full new versions of DOM trees.

Tree shaking Service

Tree shaking manages service code by looking at the import paths. If it’s imported, the tree shaker assumes that it is being used in the application.

When we inject service in @NgModule, we mention the service in import and hence this is dropped and considered as used entity by tree shaker

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { Demo1Service } from './demo1.service';

@NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
providers: [Demo1Service],
bootstrap: [AppComponent],
})
export class AppModule {}

Demo1 service is a not Tree shaking service because it is injected in app module.

If we inject service using @Injectable’s ‘providedIn’, service will be injected only when the module asks for it, if not, it will be removed by treeshaker. With ‘providedIn’ we can tell Angular which module to register our service to.

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

@Injectable({
providedIn: 'root',
})
export class Demo2Service {
constructor() {}

show() {
console.log('Demo2 Service');
}
}

Demo2 service is a Tree shaking service because it is not injected in app module.

The service itself is a class that the CLI generated and that’s decorated with @Injectable().

What exactly does providedIn do?

Determines which injectors will provide the injectable, by either associating it with an @NgModule or other InjectorType, or by specifying that this injectable should be provided in the ‘root’ injector, which will be the application-level injector in most apps.

providedIn: Type<any> | 'root' | null

providedIn: ‘root’

When you provide the service at the root level, Angular creates a single, shared instance of service and injects it into any class that asks for it. Registering the provider in the @Injectable() metadata also allows Angular to optimize an app by removing the service from the compiled app if it isn’t used.

providedIn: Module

It’s also possible to specify that a service should be provided in a particular @NgModule. For example, if you don’t want a service to be available to applications unless they import a module you’ve created, you can specify that the service should be provided in the module

import { Injectable } from '@angular/core';
import { TestModule } from './test/test.module';
import { Injectable } from '@angular/core';
import { TestModule } from './test/test.module';
@Injectable({
providedIn: TestModule,
})
export class Demo3Service {
constructor() {}
show() {
console.log('Demo3 Service');
}
}

Demo3 service is a Tree shaking service because it is not injected in app module, but only being used for test module.

This method is preferred because it enables Tree-shaking (Tree shaking is a step in a build process that removes unused code from a code base) of the service if nothing injects it.

--

--

Piyali Das

10+ yrs | Angular | Micro Frontend | Graphql | RXJS | TypeScript | JavaScript | SASS | Git | Gulp