Angular 9引入Material后编译全部组件的原因咨询
嘿,这个问题其实挺常见的,我来给你拆解一下背后的原因:
1. 全局Material主题的隐式依赖
当你通过ng add @angular/material添加Material时,CLI会自动在项目的全局样式文件(比如src/styles.scss)里引入预构建主题,类似这样:
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
这些主题文件内部会导入Material的核心样式体系,而核心样式又会间接依赖Angular CDK的多个基础模块(比如@angular/cdk/a11y、@angular/cdk/platform)以及Material核心模块。哪怕你只用到了MatButtonModule和MatToolbarModule,这些主题依赖的模块也会被编译器处理,因为样式和组件是深度绑定的。
2. 开发模式下的编译策略(Ivy特性)
Angular 9默认启用了Ivy编译器,但在开发模式(也就是npm start对应的ng serve)下,编译器的优先级是增量编译速度,而非产物最小化。为了让你后续添加组件时不用重新编译所有依赖,它会预先处理所有和当前项目有依赖关联的包——包括那些你没直接用到,但属于Material/CDK生态的模块。
但别担心,这只是开发阶段的临时现象。当你执行生产构建(ng build --prod)时,Ivy会开启严格的树摇(Tree Shaking),把所有未被实际使用的代码从最终产物里彻底剔除,此时打包出来的文件只会包含你用到的MatButton、MatToolbar以及它们的必要依赖。
3. CDK模块的依赖传递
Angular Material的组件大多基于Angular CDK(Component Dev Kit)构建。比如MatButtonModule依赖@angular/cdk/button,而cdk/button又可能依赖cdk/a11y(无障碍支持)、cdk/platform(平台检测)等基础模块。这些CDK模块之间存在共享依赖链,导致编译器需要处理整个CDK的相关模块,哪怕你没直接导入它们。
验证方法
你可以做个小测试:执行ng build --prod,然后查看dist目录下的产物大小,对比引入Material前后的变化——你会发现产物并没有因为那些“被编译”的未使用组件而大幅膨胀,这说明树摇确实生效了。
要不要优化开发模式的编译?
如果觉得开发时编译太多模块影响速度,你可以尝试:
- 移除全局预构建主题,改为自定义主题并只导入用到的组件样式(不过Material的组件样式通常随模块自动导入,主题仍需全局设置,这个方法效果有限);
- 在
angular.json的build配置里开启buildOptimizer: true和optimization: true(开发模式默认是false),但这会减慢增量编译速度,每次修改代码后的热重载会变慢,所以不推荐日常开发用。
总的来说,开发模式下的这些编译日志是正常现象,不会影响生产环境的产物大小,也不影响项目运行性能。
内容的提问来源于stack exchange,提问作者Maciej Tułaza

