Angular 19 + Module Federation (ESM) + Standalone Component → NG0200 Circular DI at...

Discussão em 'Angular' iniciado por Rajeev kotagiri, Abril 16, 2025.

  1. I have two Angular 19 applications set up with Webpack Module Federation (using the Angular CLI’s ESM‑compatible config). The host and remote both run the same Angular version (19.2.0), and I’m trying to share @angular/core as a singleton (remote declares it as a peerDependency). The remote exposes a standalone component, and the host dynamically loads and renders it via the loadRemoteModule() helper from @angular-architects/module-federation.

    When @angular/core is a peer dependency, at runtime I get a circular dependency error inside Angular’s DI: Error loading remote component: RuntimeError: NG0200: Circular dependency in DI detected for e. at throwCyclicDependencyError (_angular_core…js:583) at R3Injector.hydrate (_angular_core…js:1348) at R3Injector.get (_angular_core…js:1247) at re.getStandaloneInjector (core…js:43599) at createRootViewInjector (_angular_core…js:10877) at ComponentFactory.create (_angular_core…js:10937) at ViewContainerRef2.createComponent (…js:11135) …

    Digging into the minified stack trace, it points to an internal provider declaration in Angular core (the ɵprov that comes from defineInjectable):

    static ɵprov = defineInjectable({
    token: e,
    providedIn: 'environment',
    factory: () => new e(inject(K))
    })


    If I instead bundle @angular/core with the remote (i.e. make it a direct dependency), the error disappears—because then the remote has its own isolated DI tree.

    What I’m doing

    • Host : Angular 19 CLI app

    dependencies: "@angular/core": "19.2.0"

    Module Federation config shares all Angular packages as singletons.

    Bootstraps normally via bootstrapApplication(AppComponent, { … }).

    • Remote : Angular 19 CLI app with a standalone component RemoteComponent.

    peerDependencies: "@angular/core": "19.2.0"

    Exposes the standalone component in module-federation.config.js:

    exposes: {
    './RemoteComponent': './src/app/remote.component.ts',
    },
    shared: {
    '@angular/core': { singleton: true, strictVersion: true },
    // …other Angular packages
    }


    No custom APP_INITIALIZER or extra platform providers.

    Load & Render

    import { loadRemoteModule } from '@angular-architects/module-federation';
    // …
    loadRemoteModule({
    remoteName: 'remote',
    exposedModule: './RemoteComponent'
    }).then(m => {
    this.vcr.createComponent(m.RemoteComponent);
    });


    Observed Behavior ✅ Bundled Angular core in remote → No error.

    ⚠️ Shared Angular core as peerDependency → Circular dependency (NG0200) at getStandaloneInjector / ComponentFactory.create.

    Questions What exactly in Angular 19’s DI for standalone components is causing this cycle?

    Why does merging the host’s root injector with the standalone component’s “environment” injector trigger a circular dependency between two internal core providers (e.g. ChangeDetectionScheduler ↔ ApplicationRef)?

    What is the recommended way to share Angular core as a peer dependency while still loading remote standalone components—without bundling core in the remote or wrapping them in an NgModule?

    Any insight into the injector internals or a workaround (short of bundling core) would be greatly appreciated!

    Source Code : https://github.com/RajeevK460/ModuleFederation/tree/master/Angular-Architects

    Continue reading...

Compartilhe esta Página