Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: container.init is not a function - Angular V18 #702

Open
yvesguilherme opened this issue Nov 29, 2024 · 1 comment
Open

TypeError: container.init is not a function - Angular V18 #702

yvesguilherme opened this issue Nov 29, 2024 · 1 comment

Comments

@yvesguilherme
Copy link

yvesguilherme commented Nov 29, 2024

I am facing an issue when using @angular-architects/module-federation for Angular Module Federation. The error TypeError: container.init is not a function occurs when trying to load the remote components.

Here is the error stack trace:

core.mjs:7404 ERROR TypeError: container.init is not a function at angular-architects-module-federation-runtime.mjs:22:21 at Generator.next (<anonymous>) ...

core.mjs:7404 ERROR TypeError: container.get is not a function at angular-architects-module-federation-runtime.mjs:7:37 at Generator.next (<anonymous>) ...

Steps to reproduce:

Configure Webpack with @angular-architects/module-federation.
Try to load remote components using loadRemoteModule.
The error occurs during the ngOnInit lifecycle.

Shell

import { Component, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
import { loadRemoteModule } from '@angular-architects/module-federation';

@Component({
  selector: 'shell-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  @ViewChild('headerComponent', { read: ViewContainerRef }) headerComponent!: ViewContainerRef;
  @ViewChild('footerComponent', { read: ViewContainerRef }) footerComponent!: ViewContainerRef;

  title = 'shell';

  async ngOnInit() {
    this.loadHeader();
    this.loadFooter();
  }

  async loadHeader(): Promise<any> {
    const { HeaderComponent } = await loadRemoteModule({
      remoteEntry: 'http://localhost:4201/remoteEntry.js',
      remoteName: 'mfeCore',
      exposedModule: './HeaderComponent',
    });

    this.headerComponent.clear();
    this.headerComponent.createComponent(HeaderComponent);
  }

  async loadFooter(): Promise<any> {
    const { FooterComponent } = await loadRemoteModule({
      remoteEntry: 'http://localhost:4201/remoteEntry.js',
      remoteName: 'mfeCore',
      exposedModule: './FooterComponent',
    });

    this.footerComponent.clear();
    this.footerComponent.createComponent(FooterComponent);
  }
}

webpack configuration (shell)

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

module.exports = {
  output: {
    uniqueName: "shell",
    publicPath: "auto",
    scriptType: "text/javascript"
  },
  optimization: {
    runtimeChunk: false
  },
  resolve: {
    alias: {
      ...mf.SharedMappings.getAliases(),
    }
  },
  plugins: [
    new ModuleFederationPlugin({
      remotes: {
        "mfeCore": "mfeCore@http://localhost:4201/remoteEntry.js"
      },
      shared: mf.share({
        "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
        "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
        "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
      })
    }),
    mf.SharedMappings.getPlugin()
  ],
};

Remote webpack configuration

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


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

module.exports = {
  output: {
    uniqueName: "mfeCore",
    publicPath: "auto",
    scriptType: "text/javascript"
  },
  optimization: {
    runtimeChunk: false
  },
  resolve: {
    alias: {
      ...sharedMappings.getAliases(),
    }
  },
  experiments: {
    outputModule: true
  },
  plugins: [
    new ModuleFederationPlugin({
        // library: { type: "module" },

        // For remotes (please adjust)
        name: "mfeCore",
        filename: "remoteEntry.js",
        exposes: {
          './HeaderComponent': './projects/mfe-core/src/app/core/header/header.component.ts',
          './FooterComponent': './projects/mfe-core/src/app/core/footer/footer.component.ts',
          // './CoreModule': './projects/mfe-core/src/app/core/core.module.ts'
        },

        // For hosts (please adjust)
        // remotes: {
        //     "shell": "http://localhost:4200/remoteEntry.js"

        // },

        shared: share({
          "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
          "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
          "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
          "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },

          ...sharedMappings.getDescriptors()
        })
      // shared: {
      //   ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
      // },

    }),
    sharedMappings.getPlugin()
  ],
};

Additional information:

I have already tried adjusting the Webpack output to scriptType: 'text/javascript' as mentioned in some GitHub issues, but it did not resolve the problem.
This error does not occur if I comment out one of the asynchronous module loads (loadHeader() or loadFooter()).
I also tried using a promise.all to call the asynchronous functions and it didn't work...
Could someone please help me identify the issue?

@yvesguilherme
Copy link
Author

I forgot to add the package.json

{
  "name": "mfe-workspace",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "run:all": "node node_modules/@angular-architects/module-federation/src/server/mf-dev-server.js"
  },
  "private": true,
  "overrides": {
    "webpack": "5.88.2"
  },
  "dependencies": {
    "@angular-architects/module-federation": "^18.0.6",
    "@angular/animations": "^18.2.0",
    "@angular/cdk": "^18.2.14",
    "@angular/common": "^18.2.0",
    "@angular/compiler": "^18.2.0",
    "@angular/core": "^18.2.0",
    "@angular/forms": "^18.2.0",
    "@angular/material": "^18.2.14",
    "@angular/platform-browser": "^18.2.0",
    "@angular/platform-browser-dynamic": "^18.2.0",
    "@angular/router": "^18.2.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.10"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^18.2.12",
    "@angular/cli": "^18.2.12",
    "@angular/compiler-cli": "^18.2.0",
    "@types/jasmine": "~5.1.0",
    "jasmine-core": "~5.2.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "ngx-build-plus": "^18.0.0",
    "typescript": "~5.5.2",
    "webpack-cli": "^5.1.4"
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant