Angular 18集成Alfresco时app.config.json加载失败求助
开发连接Alfresco的Angular 18应用时遇到了旧版Angular没有的问题:应用启动时,@alfresco/adf-core加载app.config.json配置的逻辑,还没触发this.http.get请求就直接进入错误分支,提示app.config.json contains validation errors。实际底层错误是HTTP_INTERCEPTORS的DI循环依赖(NG0200),已确认配置文件URL正确。
加载配置的函数
load(callback) { return new Promise(resolve => { const configUrl = `app.config.json?v=${Date.now()}`; if (this.status === Status.INIT) { this.status = Status.LOADING; this.http.get(configUrl).subscribe(data => { this.status = Status.LOADED; this.config = Object.assign({}, this.config, data || {}); callback?.(); resolve(data); this.onDataLoaded(); }, () => { console.error('app.config.json contains validation errors'); resolve(this.config); }); } else if (this.status === Status.LOADED) { resolve(this.config); } else if (this.status === Status.LOADING) { this.onLoad.subscribe(() => { resolve(this.config); }); } }); }
当前app.config.ts代码
export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(withFetch()), provideAnimations(), importProvidersFrom( TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: TranslateLoaderService, }, }), CoreModule.forRoot(), ), ], };
旧版本NgModule代码
@NgModule({ imports: [ BrowserModule, BrowserAnimationsModule, RouterModule.forRoot(appRoutes, { initialNavigation: 'enabledNonBlocking', relativeLinkResolution: 'legacy' }), CoreModule.forRoot(), ContentModule.forRoot(), TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: TranslateLoaderService } }) ], declarations: [AppComponent, HomeComponent, LoginComponent, DocumentsComponent, AppLayoutComponent, FileViewComponent], providers: [ PreviewService, { provide: TRANSLATION_PROVIDER, multi: true, useValue: { name: 'app', source: 'resources' } } ], bootstrap: [AppComponent] }) export class AppModule {}
完整错误信息
adf-core.mjs:7011 app.config.json contains validation errors Error: NG0200: Circular dependency in DI detected for InjectionToken HTTP_INTERCEPTORS. at throwCyclicDependencyError (core.mjs:964:9) at R3Injector.hydrate (core.mjs:3127:9) at R3Injector.get (core.mjs:3005:23) at injectInjectorOnly (core.mjs:1095:36) at ɵɵinject (core.mjs:1101:40) at inject (core.mjs:1186:10) at http.mjs:1777:28 at http.mjs:1745:84 at runInInjectionContext (core.mjs:3300:12) at http.mjs:1745:46
可能的原因及解决办法
原因1:Angular 18 HttpClient新API与ADF不兼容
Angular 18引入了provideHttpClient(withFetch())作为HttpClient的独立配置方式,但ADF Core可能仍依赖传统的HttpClientModule(旧版NgModule中通过BrowserModule间接引入)。新API的拦截器注册逻辑和ADF内部的拦截器形成了循环依赖。
解决办法:
替换provideHttpClient(withFetch())为传统的HttpClientModule,在importProvidersFrom中加入该模块:
export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimations(), importProvidersFrom( HttpClientModule, // 添加这一行 TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: TranslateLoaderService, }, }), CoreModule.forRoot(), ), ], };
原因2:CoreModule加载顺序引发循环
在独立应用的importProvidersFrom中,CoreModule.forRoot()和TranslateModule的加载顺序可能导致ADF内部的HTTP拦截器与HttpClient实例互相依赖,Angular 18的DI解析逻辑比旧版更严格,触发了之前隐藏的循环。
解决办法:
调整加载顺序,确保HttpClientModule(或HttpClient相关配置)在CoreModule.forRoot()之前加载,让HttpClient实例先初始化完成。
原因3:TranslateLoaderService的依赖链循环
如果你的TranslateLoaderService依赖了ADF的ConfigService,而ConfigService又依赖HttpClient,同时TranslateModule和CoreModule一起加载,就会形成HttpClient → 拦截器 → ConfigService → TranslateLoader → HttpClient的循环链。
解决办法:
修改TranslateLoaderService的依赖注入方式,使用可选注入延迟获取依赖:
constructor(@Optional() private configService: ConfigService) {}
或者在TranslateLoader中延迟初始化相关逻辑,避免在构造阶段就触发ConfigService的加载。
内容的提问来源于stack exchange,提问作者C1B096

