Angular 4 AOT编译下路由懒加载失效问题求助
我之前在做Angular AOT项目时也碰到过一模一样的问题——JIT下懒加载正常,AOT编译无报错但就是不生效,结合你的配置和踩坑经验,给你几个具体的排查方向:
1. 先调整Rollup的打包配置(最可能的原因)
你的Rollup配置现在把所有代码打包成了单个iife格式的文件,但Angular的懒加载依赖于动态加载独立的模块chunk。iife是自执行函数,所有代码都封在一个闭包里,完全没法实现按需加载。你需要修改这几个关键配置:
- 将输出格式从
iife改为system(适配你的SystemJS环境) - 用
dir替代dest,指定输出目录让Rollup自动拆分懒加载模块为单独文件 - 确保代码拆分功能启用,不要把动态导入的模块内联进主文件
修改后的rollup.config.app.js核心部分大概是这样:
export default { entry: './src/app/app.module.aot.js', // 替换dest为output.dir output: { dir: './src/dist', format: 'system', sourceMap: true, inlineDynamicImports: false // 确保动态导入的模块拆分为单独chunk }, onwarn: function(warning) { // 保留你的警告过滤逻辑 if ( warning.message.indexOf('\'default\' is not exported by rollup') === -1 && warning.code !== 'THIS_IS_UNDEFINED' && warning.code !== 'EVAL' ) { console.warn( warning.message ); } }, plugins: [ nodeResolve({jsnext: true, module: true}), commonjs({ include: [ './node_modules/rxjs/**' ] }), uglify() ] }
2. 检查Angular编译器与懒加载模块配置
避免主模块提前导入懒加载模块
JIT模式下即使主模块导入了懒加载模块,动态加载机制还能正常工作,但AOT会静态分析代码,如果主模块直接导入了懒加载模块,它会被打包进主chunk,自然没法懒加载。确保你的AppModule里只通过loadChildren引用懒加载模块:
// 正确写法(Angular 8+) const routes: Routes = [ { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) } ]; // Angular 8之前的写法 // { path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule' }
优化Angular编译器配置
在tsconfig-aot.json的angularCompilerOptions里添加strictMetadataEmit: true,这会强制检查元数据的正确性,避免懒加载模块的元数据缺失导致AOT编译不完整:
"angularCompilerOptions": { "genDir": "../", "skipMetadataEmit": false, "skipTemplateCodegen": false, "strictMetadataEmit": true }
3. 适配SystemJS的模块加载配置
因为你的项目基于SystemJS,需要确保它能正确找到Rollup生成的懒加载chunk:
- 在
systemjs.config.js中添加dist目录的路径映射和包配置:
System.config({ paths: { 'app/*': './src/dist/*.js' }, packages: { './src/dist': { format: 'system', defaultExtension: 'js' } } });
- 检查Rollup生成的chunk文件名,确保和路由
loadChildren中的路径匹配(比如Rollup生成lazy-module.js,你的路由路径要对应上)
4. 验证AOT编译产物是否完整
进入tsconfig-aot.json中genDir指定的目录(你的配置是../,也就是项目根目录),检查是否存在每个懒加载模块对应的.ngfactory.js文件(比如lazy.module.ngfactory.js)。如果这些文件不存在,说明NGC没有识别到懒加载模块,大概率是loadChildren的语法错误,比如路径写错、模块类名拼写不对或者旧版本写法里的#分隔符缺失。
按照这个顺序排查,应该能解决你的问题。
内容的提问来源于stack exchange,提问作者Taras Kovalenko

