What could be causing the issue in my Angular code with Module Federation and Micro front-end? I'm encountering a Typescript error stating that the container is undefined

I am currently working with two separate Angular applications:

  • app1 = parentApp (the main shell application), running on port 4200
  • app2 = childApp (the micro front-end I want to integrate into parentApp), running on port 4201

I aim to utilize a component from childApp within parentApp using Module Federation. Despite numerous failed attempts following tutorials, it seems like the right approach. Prior to incorporating the component, I am focusing on routing to it.

childApp consists of an additional module containing a single component, here is some code:
childApp - app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {AbcComponent} from "./test/abc/abc.component";

const routes: Routes = [
  {path: "abc", component: AbcComponent}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

childApp - test.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AbcComponent } from './abc/abc.component';



@NgModule({
  declarations: [
    AbcComponent
  ],
  imports: [
    CommonModule
  ]
})
export class TestModule { }

childApp - abc.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-abc',
  templateUrl: './abc.component.html',
  styleUrls: ['./abc.component.scss']
})
export class AbcComponent {

}

childApp - abc.component.html

<p>abc works!</p>

childApp - app.module.ts

import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
{TestModule} from "./test/test.module"";

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    TestModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

and the most crucial childApp - webpack.config.ts

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: "childApp",
    publicPath: "auto"
  },
  optimization: {
    runtimeChunk: false
  },
  resolve: {
    alias: {
      ...sharedMappings.getAliases(),
    }
  },
  experiments: {
    outputModule: true
  },
  plugins: [
    new ModuleFederationPlugin({
        library: { type: "module" },

        //For remotes (please adjust)
        name: "childApp",
        filename: "remoteEntry.js",
        exposes: {
            './TestModule': './src/app/test/test.module.ts',
        },
        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()
        })
    }),
    sharedMappings.getPlugin()
  ],
};

parentApp is a basic application without any complexities or components. It simply contains one module and a welcome page. Let's take a look at the code.

parentApp - app.component.html

<h1>this is the parent app</h1>
<router-outlet></router-outlet>

parentApp - app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

parentApp - app.routing.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {loadRemoteModule} from "@angular-architects/module-federation";

const routes: Routes = [
  {
    path: 'childApp',
    loadChildren: () => loadRemoteModule({
      remoteEntry: 'http://localhost:4201/remoteEntry.js',
      remoteName: 'childApp',
      exposedModule: './TestModule',
    }).then(m => m.TestModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

parentApp - webpack.config.ts

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: "parentApp",
    publicPath: "auto"
  },
  optimization: {
    runtimeChunk: false
  },
  resolve: {
    alias: {
      ...sharedMappings.getAliases(),
    }
  },
  experiments: {
    outputModule: true
  },
  plugins: [
    new ModuleFederationPlugin({
        library: { type: "module" },

        remotes: {
            "childApp": "http://localhost:4201/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()
        })
    }),
    sharedMappings.getPlugin()
  ],
};

Despite being able to access http://localhost:4201/remonteEntry.js, attempting to access http://localhost:4200/childApp results in a typescript error: container is undefined.

I suspect that I might be implementing lazy loading incorrectly... Additionally, upon inspecting network requests in my browser, I noticed requests going from parentApp to childApp for all shared modules except for the specific module I intend to share, which raises some concerns.

Where could I potentially be making mistakes? Are there any typos in my code? And if you believe I am overlooking critical information here, is there any documentation or tutorial that you can recommend to assist me with this integration? Thank you.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Bug in Click Behavior of HTML5 Canvas on Webkit Browser Versions Below 535 for Android Native and iOS5 Safari

Recently, I encountered a peculiar bug in Android where positioning a canvas element on the Native Android Browser (WebKit 534.4) using css position:absolute; top:10px; left:100px; resulted in the duplicated Canvas being rendered to the browser while ignor ...

What are the tips for using ts-node in the presence of errors?

While developing, I have encountered some issues with ts-node. When I need to test something, commenting out code is my usual approach. However, when using ts-node, I keep getting this error message: 'foo' is declared but its value is never rea ...

Tips for streamlining code using switch statements in vue.js

Is there a more efficient way to simplify this switch statement for handling 5 different cases? Can I streamline the process of updating the completion status based on each step? data() { return { stepOneIsCompleted: false, ...

Populating HTML input field with AJAX response

One challenge I am facing involves a dropdown menu containing Course Titles sourced from a database in the index.php file. After capturing the selected data from the dropdown, I transmit it to a PHP file. In this PHP file, using the received Course Title, ...

When using jQuery's POST method, the "done" event is triggered, however, no data is being sent

I've been working on implementing AJAX form submission and wrote a function to handle it when the button is clicked: function putUser() { $('button#putUser').on('click', function() { var user = $('input#user' ...

How can we prevent Express static from serving the index.html file?

Encountering an issue when serving my angular 5 app from node express, where express static serves index.html for domain.com, but works correctly for domain.com/something. Can anyone help me figure out how to solve this? app.use(express.static(path.join(_ ...

Jquery outputs JSON data in a string format

When transferring a JSON object from PHP to JQuery Ajax, I am encountering an issue where the data is received as a string rather than an object. In my PHP code: $userdata=json_encode(array("FirstName"=> $fName,"LastName"=>$lName,"PhoneNumber"=> ...

Issue with URL parameter in React when using React Router

Initially, everything was running smoothly in my React project using react-router-dom. However, once I added another Route like so: <Route path="/edit/:id" component={EditPage}/> and tried changing the URL in the browser to http://localhos ...

Convert the checkbox array to comma separated values when serializing the form

I am currently working on a form that includes a dropdown menu and checkboxes: <form id="filter_form"> <select name="type"> <option value="second">second</option> </select> <input type="checkbox" name="city[ ...

Struggles with ajax and JavaScript arise when attempting to tally up grades

Currently, I am facing an issue with my JavaScript. The problem arises when trying to calculate marks for each correctly chosen answer based on information from the database. If an incorrect answer is selected, the marks are set to '0', otherwise ...

Retrieving historical data from a MySQL database to display in a div element

My main page features a button that opens a popup. Upon closing the popup, a script is triggered to call a PHP file for selecting data from the database. This selected data is then appended to a specific div within the main page: if (win.closed !== false ...

Find the element that contains a specific substring in its value using JavaScript

I am trying to find a way to count how many input fields with the class name "text" contain a specific value. document.getElementById('c_files').getElementsByClassName('text').length; Currently, this code counts all textboxes with the ...

How can you pass an authorization token in a Next.js post request when using Django REST framework?

Is there a way to successfully pass a Django authorization token in Next.js using Axios? I attempted this method, but encountered a 404 error. let token = "Token 8736be9dba6ccb11208a536f3531bccc686cf88d" await axios.post(url,{ headers ...

Struggling with validating props in React with JavaScript

Hello everyone, I'm new to JS and react so please bear with me. I've encountered an issue in the CurrentNumber component where instead of getting a number type returned, it shows [object Object]. I believe there might be a problem with my types/p ...

Analyzing conditional statements in React with State management

I've been encountering challenges with if statements correctly evaluating, displaying either true all the time or exhibiting unexpected behavior when passing variables or using state variables for evaluation. I realize this might be related to differe ...

Vue router adds hashes to paths automatically

I am currently developing a web application using Vue.js. I have implemented the vue.js webpack template and incorporated the fullpage.js framework with jQuery in my main.js file. The anchor feature of fullpage.js is utilized on my contactForm component to ...

Is there a way for me to locate the ownerID?

I have a simple task that I need to complete My goal is for the user to be identified using my token when creating a post This is how the create function looks like: exports.create = async (req, res) => { const user = req.token; const users = awai ...

Add aesthetic flair to scrollable containers

I am currently working on displaying data in columns using ngFor. However, I've run into an issue where the styles I apply to the column div are only visible on the top part of the column. As I scroll down to the bottom, the styles disappear. I believ ...

What is the best way to conceal the button?

I'm working on a program that involves flipping cards and creating new ones using three components: App, CardEditor, and CardViewer. Within the CardEditor component, I am trying to implement a function that hides the button leading to CardViewer until ...

Go through the fields of Vue components iteratively

I've created a Vue component that has over 40 properties which represent a form for editing a business entity. The process flow goes as follows: Upon mounting, the data is fetched from the server in JSON format and used to initialize the component p ...