-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Description
🐞 Bug report
Command (mark with an x)
- build
Description
Looks like Ivy prevents tree shaking of not referenced components/injectables. It's either a bug, or positive difference in build size can only be seen if application code actually uses all features of all dependencies, which is not realistic.
🔬 Minimal Reproduction
- Create a minimal application:
ng new --defaults --minimal -S -s -t -g ivy-size - Build with and without ivy to measure bundle sizes of an empty app:
- With
"enableIvy": false:main-es2015is 125 kB - With
"enableIvy": true:main-es2015is 103 kB ✔️
- Install package angular2-toaster:
npm i angular2-toaster - Import
ToasterModuleinapp.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ToasterModule } from 'angular2-toaster';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
ToasterModule.forRoot(),
],
bootstrap: [AppComponent]
})
export class AppModule { }
- Build with and without ivy again:
- With
"enableIvy": false:main-es2015is 131 kB (increased by 6 kB) - With
"enableIvy": true:main-es2015is 144 kB❌(increased by 41 kB)
- Add
<toaster-container></toaster-container>toapp.component.ts - Build again:
- With
"enableIvy": false:main-es2015is 146 kB - With
"enableIvy": true:main-es2015is 144 kB
Sizes equalized, but now compare the final size with the size of an empty app:
- build with
"enableIvy": falseincreased by (146-125)=21 kB - build with
"enableIvy": trueincreased by (144-103)=41 kB
I tried to make builds with command NG_BUILD_DEBUG_OPTIMIZE=minify ng build --prod and I noticed this difference in builds:

[ngSwitch] is used in component [toastComp], which is used by component <toaster-container>. But in <toaster-container>, component [toastComp] will not be displayed unless there's at least one element in array toasts. And to add an element I need to inject service ToasterService, which I do not do in my little app.
Here's my attempt to reproduce the issue without dependencies:
- Create a minimal application:
ng new --defaults --minimal -S -s -t -g ivy-size - Build with and without ivy to measure bundle sizes of an empty app:
- With
"enableIvy": false: main-es2015 is 125 kB - With
"enableIvy": true: main-es2015 is 103 kB ✔️
- Replace
app.module.tswith:
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { Component, NgModule } from '@angular/core';
@Component({
selector: 'app-root',
template: '<child-component *ngIf="false"></child-component>',
})
export class AppComponent {}
@Component({
selector: 'child-component',
template: '<input ngModel>',
})
export class ChildComponent {}
@NgModule({
imports: [
BrowserModule,
CommonModule,
FormsModule,
],
declarations: [AppComponent, ChildComponent],
bootstrap: [AppComponent]
})
export class AppModule {}Lets build it:
- With
"enableIvy": false:main-es2015is 158 kB - With
"enableIvy": true:main-es2015is 157 kB ❌
the initial positive difference in size is gone.
Lets build with NG_BUILD_DEBUG_OPTIMIZE=minify&&ng build --prod:
By looking at difference in builds I can see that not used features of CommonModule are not removed:


Interestingly, some not referenced classes of @angular/forms are removed: I can find RadioControlValueAccessor but not PatternValidator or NgSelectOption.
🌍 Your Environment
Angular CLI: 9.0.2
Node: 12.13.0
OS: win32 x64
Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: No
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.900.2
@angular-devkit/build-angular 0.900.2
@angular-devkit/build-optimizer 0.900.2
@angular-devkit/build-webpack 0.900.2
@angular-devkit/core 9.0.2
@angular-devkit/schematics 9.0.2
@angular/cli 9.0.2
@ngtools/webpack 9.0.2
@schematics/angular 9.0.2
@schematics/update 0.900.2
rxjs 6.5.4
typescript 3.7.5
webpack 4.41.2Anything else relevant?
I tried to set "sideEffects": false, in package.json of angular2-toaster, it didn't help.

