Skip to content

NG_VALUE_ACCESSOR as a separate variable retains dead code in Angular CLI 11 #19572

Closed
@devoto13

Description

@devoto13

🐞 Bug report

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Yes. It is not present in the fresh project generated with Angular CLI 10.

Description

While debugging a size regression in ng-bootstrap (ng-bootstrap/ng-bootstrap#3904 (comment)) when used in Angular 11 application I've spotted that a lot of dead code is retained because NG_VALUE_ACCESSOR is declared as a separate variable. Such pattern retains a linked component and consequently a lot of extra code used by this component. E.g. below code in the library will retain MylibComponent using Angular CLI 11, but will be removed as dead code using Angular CLI 10:

const TEST_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => MylibComponent),
  multi: true,
};

@Component({
  selector: 'lib-mylib',
  template: ` <p>mylib works!</p> `,
  styles: [],
  providers: [TEST_VALUE_ACCESSOR],
})
export class MylibComponent implements OnInit, ControlValueAccessor { ... }

Observations:

  • This only happens when code is present in the library. Component is eliminated as dead code if it is part of the application.
  • Inlining the variable will result in component being eliminated as dead code.
  • Library code processed by ngcc is identical, so I guess something in the application bundling has changed.

🔬 Minimal Reproduction

  1. Clone the reproductions for Angular 10 and 11 (fresh project + fresh lib + minimal code reproducing the problem, each in a separate commit):

    git clone -b va10 git@github.com:devoto13/va-regression-repro.git va10
    git clone -b va11 git@github.com:devoto13/va-regression-repro.git va11
    
  2. Build each repro:

    yarn ng build mylib --prod
    NG_BUILD_MANGLE=false ./node_modules/.bin/ng build --prod
    
  3. Check dist/va10/main.js and dist/va11/main.js respectively. Observe that in v10 project MylibComponent symbol is not present in the bundle, but in v11 project this symbol is retained in the bundle together with the value accessor.

🌍 Your Environment

Angular CLI: 11.0.3
Node: 14.8.0
OS: darwin x64

Angular: 11.0.3
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1100.3
@angular-devkit/build-angular   0.1100.3
@angular-devkit/core            11.0.3
@angular-devkit/schematics      11.0.3
@schematics/angular             11.0.3
@schematics/update              0.1100.3
ng-packagr                      11.0.3
rxjs                            6.6.3
typescript                      4.0.5

Anything else relevant?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions