Angular5.2升级至6后,含MatDialog注入的组件Prod模式加载失败
我之前在升级Angular版本时也碰到过几乎一模一样的问题——dev模式下一切正常,但用ng serve --prod或者ng build --prod(自动开启AOT)就会抛出TypeError: factory is not a function的错误,结合自己的排查和社区的解决方案,给你几个针对性的修复方向:
1. 确保所有Angular相关依赖版本完全匹配
Angular 6对依赖版本的一致性要求比之前更严格,哪怕是小版本差异都可能导致AOT编译时的工厂函数异常。你当前的@angular/core等核心包是6.0.0,但@angular/material和@angular/cdk是6.0.1,建议把这两个包降级到6.0.0,保持和核心版本完全一致:
npm install @angular/material@6.0.0 @angular/cdk@6.0.0 --save
同时检查package.json里其他第三方库(比如@angular/flex-layout)是否明确标注了兼容Angular 6的版本,避免版本不兼容导致的编译问题。
2. 检查NgModule中是否正确导入了Material模块
AOT编译要求所有用到的组件/服务对应的模块必须在当前NgModule中显式导入,如果你在组件里注入了MatDialog或MatBottomSheet,但没有在所在模块的imports数组里添加对应的模块,就会导致生产模式下服务无法被正确实例化:
import { MatDialogModule, MatBottomSheetModule } from '@angular/material'; @NgModule({ imports: [ // ...其他模块 MatDialogModule, MatBottomSheetModule ], // ...其他配置 }) export class YourFeatureModule { }
注意:不要手动在providers数组里添加MatDialog或MatBottomSheet服务,这些服务已经通过各自的模块自动提供,重复添加会导致注入冲突。
3. 清理缓存与重建依赖
升级后残留的旧依赖缓存或编译产物经常会导致各种奇怪的问题,按以下步骤彻底清理:
- 删除
node_modules文件夹:# Windows rmdir /s/q node_modules # macOS/Linux rm -rf node_modules - 清理npm缓存:
npm cache clean --force - 重新安装依赖:
npm install - 清理Angular的编译缓存和dist文件夹:
ng clean - 最后尝试重新构建生产版本:
ng build --prod
4. 检查tsconfig.json的编译配置
Angular 6的AOT编译对TypeScript配置有特定要求,确保你的tsconfig.json里有以下关键配置:
{ "compilerOptions": { "target": "es2015", "module": "es2015", "moduleResolution": "node", "strict": true, "strictTemplates": true }, "angularCompilerOptions": { "enableIvy": false, // Angular 6还不支持Ivy,确保关闭 "fullTemplateTypeCheck": true, "strictInjectionParameters": true } }
尤其是strictTemplates和strictInjectionParameters这两个选项,能帮你提前发现AOT编译时的注入问题。
5. 排查组件中的AOT不兼容语法
AOT编译不支持一些动态或运行时的语法,检查你的组件代码:
- 避免在构造函数中进行复杂的运行时操作,保持构造函数只做依赖注入
- 确保所有绑定的模板变量、输入输出属性都有明确的类型定义
- 不要使用
require()等CommonJS语法加载模板或样式,改用Angular的templateUrl/styleUrls
如果以上方法都没解决问题,可以尝试临时关闭AOT编译来验证(虽然不推荐生产环境这么做),在angular.json的build配置里将aot设为false,然后运行ng build --prod,如果能正常构建,说明问题确实出在AOT编译的配置或依赖上,可以进一步缩小排查范围。
内容的提问来源于stack exchange,提问作者Kake

