AngularJS迁移Angular13双启动遇PlatformLocation JIT编译失败问题
AngularJS 迁移至 Angular 13 双启动模式 JIT 编译错误解决方案
错误信息
Uncaught Error: 可注入对象 'PlatformLocation' 需要使用 JIT 编译器编译,但 '@angular/compiler' 不可用。 该可注入对象属于一个已被部分编译的库。 但 Angular Linker 未处理该库,无法回退到 JIT 编译。 理想情况下,应使用 Angular Linker 处理该库以实现完全 AOT 编译。 或者,通过 '@angular/platform-browser-dynamic' 或 '@angular/platform-server' 引导应用来加载 JIT 编译器, 或者在引导前手动导入 'import "@angular/compiler";' 以提供编译器。
当前双启动配置(main.ts)
// AngularJS 相关导入 import { DoBootstrap, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @NgModule({ imports: [ BrowserModule, UpgradeModule ] }) export class AppModule{ // 覆盖 Angular 引导逻辑,使其不执行默认引导操作 ngDoBootstrap() {} } // 使用 UpgradeModule 进行引导 platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => { console.log("以 Angular & AngularJS 混合模式引导应用"); const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule; upgrade.bootstrap(document.body, ['codecraft']); });
需求与已尝试方案
- 不希望通过
import '@angular/compiler';临时解决(后续迁移组件会重复出现问题) - 不关闭AOT或Ivy编译模式
- 已尝试:
- 在package.json中配置
"postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points" - 执行
npm update - 在webpack配置中使用babel-loader
- 在package.json中配置
可行解决方案
1. 完整执行ngcc编译
调整package.json中的postinstall脚本,移除--first-only参数,确保ngcc编译所有依赖库(包括UpgradeModule相关的兼容Ivy的入口):
"postinstall": "ngcc --properties es2015 browser module main --create-ivy-entry-points"
执行以下步骤:
- 删除
node_modules目录和dist目录 - 执行
npm install触发完整的postinstall脚本 - 重新构建项目
2. 统一Angular依赖版本
检查package.json中所有@angular/*包的版本是否均为13.x.x,避免版本不一致导致的兼容性问题。统一版本后执行npm install更新依赖。
3. 启用Angular Linker
在angular.json的项目build配置中添加Linker设置,强制处理未兼容Ivy的第三方库:
"architect": { "build": { "options": { "allowedCommonJsDependencies": ["angular"], "linker": { "enabled": true, "force": true } } } }
4. 调整UpgradeModule引导逻辑
将UpgradeModule的引导逻辑移至ngDoBootstrap方法内,避免异步回调可能导致的注入器问题:
import { DoBootstrap, NgModule, Injector } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @NgModule({ imports: [ BrowserModule, UpgradeModule ] }) export class AppModule implements DoBootstrap{ constructor(private injector: Injector) {} ngDoBootstrap() { const upgrade = this.injector.get(UpgradeModule); upgrade.bootstrap(document.body, ['codecraft']); } } platformBrowserDynamic().bootstrapModule(AppModule);
内容的提问来源于stack exchange,提问作者mandav
相关产品推荐
相关产品推荐

