Angular 15 HMR失效,抛出NG0200循环依赖错误
解决Angular 15升级后HMR的DI循环依赖问题
问题原因
Angular 15对依赖注入的循环检测逻辑进行了强化,原HMR实现中在hot.dispose回调内通过模块注入器直接获取ApplicationRef时,触发了ApplicationRef与模块注入器之间的隐式循环依赖,导致抛出NG0200错误。
解决方案
方案1:提前缓存ApplicationRef
在bootstrap成功后立即获取并保存ApplicationRef,避免在销毁阶段再去触发依赖解析:
修改hmr.ts文件:
import { NgModuleRef, ApplicationRef } from '@angular/core'; import { createNewHosts } from '@angularclass/hmr'; export const hmrBootstrap = ( module: any, bootstrap: () => Promise<NgModuleRef<any>> ) => { let ngModule: NgModuleRef<any>; let appRef: ApplicationRef; module.hot.accept(); bootstrap().then(mod => { ngModule = mod; appRef = mod.injector.get(ApplicationRef); // 提前获取并缓存 }); module.hot.dispose(() => { if (!ngModule || !appRef) return; const elements = appRef.components.map(c => c.location.nativeElement); const makeVisible = createNewHosts(elements); ngModule.destroy(); makeVisible(); }); };
方案2:使用skipSelf选项获取实例
在获取ApplicationRef时添加skipSelf配置,跳过当前模块注入器,从父级平台注入器获取实例,规避循环依赖:
修改hmr.ts中hot.dispose内的代码:
// 替换原获取ApplicationRef的行 const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef, null, { skipSelf: true });
方案3:迁移到官方内置HMR支持
@angularclass/hmr已停止维护,Angular 14+官方CLI已集成HMR功能,推荐迁移:
- 卸载旧依赖:
npm uninstall @angularclass/hmr
- 删除自定义的
hmr.ts文件 - 更新
main.ts为官方版本:
import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); } const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule); if (environment.hmr) { import('@angular-devkit/build-angular/src/webpack/hmr').then(({ hmrBootstrap }) => { hmrBootstrap(module, bootstrap); }); } else { bootstrap().catch(err => console.error(err)); }
- 启动时使用
ng serve --hmr,或在angular.json的serve配置中添加"hmr": true
验证
重启开发服务器,启用HMR模式,检查是否仍存在循环依赖错误,同时验证模块热替换功能是否正常工作。
内容的提问来源于stack exchange,提问作者Rohit Parte
相关产品推荐
相关产品推荐

