Thanks to Filipe Silva who reviewed this article and to Rob Wormald for a lot of insights regarding this technology. Also thanks to Sander Elias who gave important feedback.
Update 2017-11-06: Since Angular CLI 1.5, the Build Optimizer is enabled by default during production builds.
Starting with release 1.3.0-rc.0, the Angular CLI incorporates the Angular Build Optimizer. This clever utility modifies the generated JavaScript output to enhance the effectiveness of tree shaking. The outcome can be substantial reductions in bundle size. Below, I walk through a few straightforward examples that highlight what this new tool can achieve. If you'd like to try them out yourself, the complete source code is available in my GitHub repository.
Keep in mind that the Angular Build Optimizer was still in an experimental phase at the time of writing. Consequently, its behavior may evolve. Even so, as demonstrated below, it offers considerable promise for reducing bundle sizes.
First Test Case
To illustrate the impact of the Angular Build Optimizer, I've put together a basic Angular application using the Angular CLI. Right after scaffolding, I brought in MdButtonModule and MdCheckboxModule from Angular Material, along with Angular's NoopAnimationsModule and FormsModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { MdButtonModule, MdCheckboxModule } from '@angular/material';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from "@angular/forms";
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
NoopAnimationsModule,
MdButtonModule,
MdCheckboxModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
It's worth noting that I don't actually use any of these modules in the application. They were added purely to test how effectively the CLI and webpack, working with the Angular Build Optimizer, can discard them during the build.
Next, I generated two production builds: one without the Build Optimizer and one with it. For the latter, I used the new --build-optimizer command line option:
ng build --prod --build-optimizer=false
For the former, you can simply run a standard production build, as the Build Optimizer is now active by default starting with CLI 1.5. In earlier versions, you'd have to explicitly pass the --build-optimizer flag:
ng build --prod --build-optimizer
The outcomes are quite striking:
As the figure reveals, the bundle size after tree shaking is roughly halved when the Angular Build Optimizer is applied. This aligns with observations I documented a few months back: certain conditions can hinder tree shaking implementations from performing optimally. The Build Optimizer appears to address these blockages.
Second Test Case
Following that, I introduced one component from each of the two Angular Material modules into the application to see if this would change the tree shaking behavior:
<!-- app.component.html -->
<button md-raised-button (click)="doIt()">Raised button</button>
<md-checkbox class="example-margin" [(ngModel)]="checked">Checked</md-checkbox>
This produced the following numbers:
Naturally, both bundles grew in size since more of the included packages are now being utilized. However, consistent with the first test, the bundles are still approximately half the size when the Angular Build Optimizer is employed.
Third Test Case
You might be curious about the overhead that the two Angular Material modules contribute in the scenarios above. To investigate, I stripped out all references to those modules and ran two more builds—one with the Angular Build Optimizer and one without:
When comparing this to the first scenario, it's evident that with the Build Optimizer, nearly all of the unused Material Design module code can be eliminated, even if those modules are imported but not referenced in the application.
Known Constraints
As highlighted earlier, the Angular Build Optimizer was still experimental at the time this was written, so its implementation might shift. At present, it may cause certain problems during source code transformation. For example, source maps are currently broken when building for production with the Optimizer. There's also an issue related to rxjs operators and another concerning console logs. Additionally, complications may surface when using getters that have side effects, as the optimizer leverages UglifyJS' pure_getters setting. This configuration prompts Uglify to strip out unused getter calls, which can be problematic if you rely on those side effects. Be aware that such issues might also surface within third-party packages that are outside your direct control.
Despite these caveats, the Build Optimizer clearly has significant potential.
Final Thoughts
The Angular Build Optimizer clears away the obstacles that were preventing tree shaking tools from performing at their best. This can lead to dramatic shrinkage in bundle size.



