Skip to content

bug(MatListModule): Should not import @angular/forms in main chunk if it's just using mat-nav-list #19562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
csbenjamin opened this issue Dec 2, 2020 · 6 comments

Comments

@csbenjamin
Copy link

Reproduction

Steps to reproduce:

  1. Execute ng new angular-test --routing=true & cd angular-test
  2. Execute ng add @angular/material
  3. Import MatListModule into the AppModule and insert <mat-nav-list></mat-nav-list> into app.component.html
  4. Execute ng generate module --route lazy --module app
  5. Import MatInputModule into LazyModule
  6. Insert <input matInput /> into lazy.component.html

Or just clone my repository csbenjamin/issue-with-tree-shake

  1. Execute ng build --prod

Expected Behavior

@angular/forms should be imported in the chunk lazy loaded.

Actual Behavior

@angular/forms is being imported in the main chunk.

Note that if we remove the lazy route from app.routing.module.ts, then @angular/forms goes away from the main chunk, even using mat-nav-list in app.component.html. Also, if we keep the lazy route and remove the MatListModule dependency from the AppModule, then the @angular/forms goes to the lazy chunk, as it should be.

A possible solution would be spliting list.ts and selection-list.ts into two different NgModule, so, if we are not using the selection-list.ts part, we just import the NgModule that contains list.ts, which does not depend on @angular/forms.

Environment


Angular CLI: 10.1.7
Node: 14.8.0
OS: linux x64

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

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1001.7
@angular-devkit/build-angular   0.1001.7
@angular-devkit/core            10.1.7
@angular-devkit/schematics      10.1.7
@angular/cdk                    10.2.7
@angular/cli                    10.1.7
@angular/material               10.2.7
@schematics/angular             10.1.7
@schematics/update              0.1001.7
rxjs                            6.6.3
typescript                      4.0.5
@crisbeto
Copy link
Member

crisbeto commented Dec 7, 2020

Splitting the selection list into a separate module would be a big breaking change at this point and it'll make the setup inconsistent with the rest of the library where we have one module per entry point. Furthermore, we're only using one constant from the forms module (NG_VALUE_ACCESSOR) so you probably aren't getting the entire module, unless there's something else in the same chunk that's importing more of the module.

@crisbeto crisbeto closed this as completed Dec 7, 2020
@csbenjamin
Copy link
Author

@crisbeto Did you see the reproduction repository or the reproduction steps? It is a clean application. Can you see why @angular/forms is getting into the main chunk?

@crisbeto
Copy link
Member

crisbeto commented Dec 7, 2020

Looking through it, the module definitely gets pulled in because of the Material list, but I'm not sure why it's not limited to the one constant that we're actually using. This would be a better question for the CLI repository: https://github.com/angular/angular-cli/issues. I'll reopen the issue and transfer it there.

@crisbeto crisbeto reopened this Dec 7, 2020
@crisbeto crisbeto transferred this issue from angular/components Dec 7, 2020
@clydin
Copy link
Member

clydin commented Dec 7, 2020

The FESM output of the libraries causes each package entry point to be one large JavaScript module. This module will be located in the earliest application output chunk that uses the package entry point. Since Material is being used in the main output chunk and Material is using the forms package, the full forms JavaScript module must be placed in the main chunk to ensure accessibility for the Material code. The dead code elimination passes will remove code from the forms JavaScript module that is unused within the full application. However, any used forms code will be moved along with the forms JavaScript module into the main output chunk.
Using the ESM output of libraries would greatly mitigate this as only the code within each individual JavaScript module would be included instead of the entire library entry point. Unfortunately, using the ESM library output with Webpack (the bundler internally used with the Angular CLI) has resulted in even larger output bundle sizes. This negated the benefit of using ESM library output for cases such as this. However, the usage of FESM and ESM is periodically reevaluated as bundler and optimization techniques evolve so this could change in the future.

@alan-agius4
Copy link
Collaborator

Duplicate of #19527 (comment) and #13635

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jan 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants