webpack-5angular14angular-module-federation

Cannot find microfrontend module providers after update to Angular 14


I'm new to Module Federation and Webpack, but I found myself to work to an Angular project with that technologies. I updated the workspace from Angular 12 to Angular 14 and migrated Module Federation too to 14.3 version. My microfrontend exposes a module that has imports, declarations, providers, exports. The plugin is loaded with the following code:

loadRemoteModule({
            type: "script",
            remoteEntry,
            remoteName,
            exposedModule,
        })
            .then(container => {
                const ngModule = container[moduleName];
                this.moduleRef = createNgModule(ngModule, this.injector);
            });

this.moduleRef is a variable where I cache the module, so I can access it to render dynamically components, in this way:

@Component({
    selector: "my-component",
    templateUrl: "./my-component.component.html",
    styleUrls: ["./my-component.scss"],
})
export class MyComponent

    @ViewChild("container", { read: ViewContainerRef, static: false }) container:                   ViewContainerRef;
    private _containerRef: ComponentRef<any>;

[...]

    renderLazyComponent(myComponent): void {
        const componentFactory =  this.moduleRef.componentFactoryResolver.resolveComponentFactory(myComponent);
        this._containerRef.createComponent(componentFactory);
    }

The component is rendered correctly, but it seems that services provided by this.moduleRef are not resolved (The runtime error "No provider for k => k => k =< k").

This code worked for Angular 12. I don't think the issue is with Module Federation... I think there's something wrong with the lazy loaded module, maybe something in the way the compiler works with dynamic components changed. Host application and microfrontends live in different repo, so I can't use Nx to resolve my issue. Any suggestion is really appreciated.


Solution

  • It seems that with ng13+ the Angular method "createComponent" had changed and that the parameter "moduleRef" is almost always needed, even if it is marked as optional. So I created a dictionary of external module references and components, so I can retrieve a specific external module when I need to render one of its component. This solution works, but it is a sort of workaround. The next step will be remove all external modules and rewrite components as standalone, so the providers will be resolved and there will be no need to create the previous dictionary.