3

I'm implementing module federation in my Angular project, below is my Microfrontend's webpack.config.js

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const share = mf.share;

const sharedMappings = new mf.SharedMappings();
sharedMappings.register(path.join(__dirname, "tsconfig.json"), [
  /* mapped paths to share */
]);

module.exports = {
  output: {
    uniqueName: "mfe1",
    publicPath: "auto",
  },
  optimization: {
    runtimeChunk: false,
  },
  resolve: {
    alias: {
      ...sharedMappings.getAliases(),
    },
  },
  plugins: [
    new ModuleFederationPlugin({
      // For remotes (please adjust)
      name: "mfe",
      filename: "remoteEntry.js",
      exposes: {
        "./Module": "./src/app/microfrontend/microfrontend.module.ts",
        "./TestComponent": "./src/app/microfrontend/test/test.component.ts",
      },
   
      shared: share({
        "@angular/core": { singleton: true, strictVersion: false, requiredVersion: "auto" },
        "@angular/common": { singleton: true, strictVersion: false, requiredVersion: "auto"},
        "@angular/common/http": { singleton: true, strictVersion: false, requiredVersion: auto" },
        "@angular/router": { singleton: true, strictVersion: false, requiredVersion: "auto" },
            ...sharedMappings.getDescriptors(),
      }),
    }),
    sharedMappings.getPlugin(),
  ],
};

In shell, I have setup routing to load mfe on path /remote which is i could navigate on shell without any issue. Below is my route path

{
    path: 'remote',
    loadChildren: () =>
      loadRemoteModule({
        remoteEntry: 'http://localhost:3000/remoteEntry.js',
        remoteName: 'mfe',
        exposedModule: './Module',
      }).then((m) => {
        return m.MicrofrontendModule;
      }),
}

I'm trying to load TestComponent from MFE into shell using below directive and service

mfe-load-directive.ts

import { Directive, Input, OnChanges, ViewContainerRef } from '@angular/core';

import { MFELoaderService } from './mfe-loader.service';

@Directive({
    selector: '[appMicrofrontendLoader]'
})

export class MFELoaderDirective implements OnChanges {

    @Input() appMFELoader!: any;

    constructor(
        private viewContainerRef: ViewContainerRef,
        private loaderService: MFELoaderService
    ) { }
    
    ngOnChanges(): void {
        this.loaderService.loadMFE(this.viewContainerRef);
    }
}

mfe-loader.service.ts

import { loadRemoteModule } from "@angular-architects/module-federation";
import { ComponentRef, Injectable, ViewContainerRef } from "@angular/core";


@Injectable({
    providedIn: 'root'
})

export class MFELoaderService {
    public loadMFE(viewContainerRef: ViewContainerRef) {
        let data = {
            "remoteUrl" : "http://localhost:3000",
            "path": "/remoteEntry.js",
            "name": "mfe",
            "component": "TestComponent",   
        };
        const url = data.remoteUrl;
        loadRemoteModule({
            type: 'module',
            remoteEntry: `${url}${data.path}`,
            exposedModule: `./${data.component}`
        }).then(m => {
            viewContainerRef.clear();
            const component: ComponentRef<any> = viewContainerRef.createComponent(m[data.component]);
        });
    }
}

Template

<div [appMFELoader]="'doNothing'"></div>

When i try to access MFE on route http://localhost:4200/remote, I'm able to load the MFE, but if it try to load TestComponent by using viewContainerRef.createComponent() method getting below errors

Error: Uncaught (in promise): TypeError: container.init is not a function Error: Uncaught (in promise): TypeError: container.get is not a function

Can I get some help to resolve it?

VIK6Galado
  • 650
  • 14
  • 32
  • 1
    Do TestComponent is part of the module microfrontend.module ? – FolabiAhn Oct 08 '22 at 21:36
  • Yes its part of module microfrontend.module – VIK6Galado Oct 09 '22 at 08:08
  • So why how are you exposing it since you are already exposing his module ? If it is the main entrypoint to your module, just add it to the routes of the modules as default. – FolabiAhn Oct 10 '22 at 19:13
  • Hi, any solution on this? I agree with FolabiAhn that exposinbg both Module and component might not be the best approach, anyway, I don't think that should be the root cause. In fact I am reproducing your issue without having the component exposed – BalB May 03 '23 at 06:44

0 Answers0