I have created a application with :
<code>npx create-nx-workspace@latest angular -monorepo --preset=angular-monorepo
<code>npx create-nx-workspace@latest angular -monorepo --preset=angular-monorepo
</code>
npx create-nx-workspace@latest angular -monorepo --preset=angular-monorepo
and added host and a remote application with nx extention available on vs-code.
here the both are working as expected running the host will automatically run the remote(in localhost:4204) also in the nx workspace, accessing the host on localhost:4203 and routing to localhost:4203/remote1 will display the remote content in the host.
host configurations: app.routes.ts
<code>import { authGuard } from './auth.guard';
import { NxWelcomeComponent } from './nx-welcome.component';
import { Route } from '@angular/router';
export const appRoutes: Route[] = [
loadChildren: () => import('remote1/Routes').then((m) => m.remoteRoutes),
canActivate: [authGuard],
component: NxWelcomeComponent,
<code>import { authGuard } from './auth.guard';
import { NxWelcomeComponent } from './nx-welcome.component';
import { Route } from '@angular/router';
export const appRoutes: Route[] = [
{
path: 'remote1',
loadChildren: () => import('remote1/Routes').then((m) => m.remoteRoutes),
canActivate: [authGuard],
},
{
path: '',
component: NxWelcomeComponent,
},
];
</code>
import { authGuard } from './auth.guard';
import { NxWelcomeComponent } from './nx-welcome.component';
import { Route } from '@angular/router';
export const appRoutes: Route[] = [
{
path: 'remote1',
loadChildren: () => import('remote1/Routes').then((m) => m.remoteRoutes),
canActivate: [authGuard],
},
{
path: '',
component: NxWelcomeComponent,
},
];
module-federation.config.ts
<code>import { ModuleFederationConfig } from '@nx/webpack';
const config: ModuleFederationConfig = {
<code>import { ModuleFederationConfig } from '@nx/webpack';
const config: ModuleFederationConfig = {
name: 'host',
remotes: ['remote1'],
};
export default config;
</code>
import { ModuleFederationConfig } from '@nx/webpack';
const config: ModuleFederationConfig = {
name: 'host',
remotes: ['remote1'],
};
export default config;
host app app.component.html
<code><ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
<router-outlet></router-outlet>
<code><ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
</ul>
<router-outlet></router-outlet>
</code>
<ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
</ul>
<router-outlet></router-outlet>
/////////////////////////////////
remote1 configurations: app.routes.ts
<code>import { Route } from '@angular/router';
export const appRoutes: Route[] = [
import('./remote-entry/entry.routes').then((m) => m.remoteRoutes),
<code>import { Route } from '@angular/router';
export const appRoutes: Route[] = [
{
path: '',
loadChildren: () =>
import('./remote-entry/entry.routes').then((m) => m.remoteRoutes),
},
];
</code>
import { Route } from '@angular/router';
export const appRoutes: Route[] = [
{
path: '',
loadChildren: () =>
import('./remote-entry/entry.routes').then((m) => m.remoteRoutes),
},
];
module-federation.config.ts
<code>import { ModuleFederationConfig } from '@nx/webpack';
const config: ModuleFederationConfig = {
'./Routes': 'apps/remote1/src/app/remote-entry/entry.routes.ts',
'./RemoteComponent' : 'apps/remote1/src/app/remote-entry/entry.component.ts'
<code>import { ModuleFederationConfig } from '@nx/webpack';
const config: ModuleFederationConfig = {
name: 'remote1',
exposes: {
'./Routes': 'apps/remote1/src/app/remote-entry/entry.routes.ts',
'./RemoteComponent' : 'apps/remote1/src/app/remote-entry/entry.component.ts'
},
};
export default config;
</code>
import { ModuleFederationConfig } from '@nx/webpack';
const config: ModuleFederationConfig = {
name: 'remote1',
exposes: {
'./Routes': 'apps/remote1/src/app/remote-entry/entry.routes.ts',
'./RemoteComponent' : 'apps/remote1/src/app/remote-entry/entry.component.ts'
},
};
export default config;
These are my nx workspace remote and host app , I need to access this remote1 in my angular application created with ng new host, added module federation with
<code>ng add @angular-architects/module-federation --project host --port 4200
<code>ng add @angular-architects/module-federation --project host --port 4200
</code>
ng add @angular-architects/module-federation --project host --port 4200
webpack.config.js
<code>const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
path.join(__dirname, 'tsconfig.json'),
[/* mapped paths to share */]);
scriptType: "text/javascript"
...sharedMappings.getAliases(),
new ModuleFederationPlugin({
// library: { type: "Routes" },
// For remotes (please adjust)
// filename: "remoteEntry.js",
// './Component': './/src/app/app.component.ts',
// For hosts (please adjust)
"remote1": "remote1@http://localhost:4204/remoteEntry.mjs",
// "@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()
<code>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: "hostApp",
publicPath: "auto",
scriptType: "text/javascript"
},
optimization: {
runtimeChunk: false
},
resolve: {
alias: {
...sharedMappings.getAliases(),
}
},
experiments: {
outputModule: true
},
plugins: [
new ModuleFederationPlugin({
// library: { type: "Routes" },
// For remotes (please adjust)
// name: "hostApp",
// filename: "remoteEntry.js",
// exposes: {
// './Component': './/src/app/app.component.ts',
// },
// For hosts (please adjust)
remotes: {
"remote1": "remote1@http://localhost:4204/remoteEntry.mjs",
},
// 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()
],
};
</code>
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: "hostApp",
publicPath: "auto",
scriptType: "text/javascript"
},
optimization: {
runtimeChunk: false
},
resolve: {
alias: {
...sharedMappings.getAliases(),
}
},
experiments: {
outputModule: true
},
plugins: [
new ModuleFederationPlugin({
// library: { type: "Routes" },
// For remotes (please adjust)
// name: "hostApp",
// filename: "remoteEntry.js",
// exposes: {
// './Component': './/src/app/app.component.ts',
// },
// For hosts (please adjust)
remotes: {
"remote1": "remote1@http://localhost:4204/remoteEntry.mjs",
},
// 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()
],
};
app.routes.ts
<code>import { loadRemoteModule } from '@angular-architects/module-federation';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
export const routes: Routes = [
{ path: "",component: AppComponent},
{path: "remote1", loadChildren: () =>{
return loadRemoteModule({
remoteEntry : "http://localhost:4204/remoteEntry.mjs",
exposedModule: "remote1/RemoteComponent"
}).then(m => m.RemoteComponentModule).catch(err => console.log(err))
<code>import { loadRemoteModule } from '@angular-architects/module-federation';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
export const routes: Routes = [
{ path: "",component: AppComponent},
{path: "remote1", loadChildren: () =>{
return loadRemoteModule({
remoteEntry : "http://localhost:4204/remoteEntry.mjs",
remoteName : "remote1",
exposedModule: "remote1/RemoteComponent"
}).then(m => m.RemoteComponentModule).catch(err => console.log(err))
}
},
];
</code>
import { loadRemoteModule } from '@angular-architects/module-federation';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
export const routes: Routes = [
{ path: "",component: AppComponent},
{path: "remote1", loadChildren: () =>{
return loadRemoteModule({
remoteEntry : "http://localhost:4204/remoteEntry.mjs",
remoteName : "remote1",
exposedModule: "remote1/RemoteComponent"
}).then(m => m.RemoteComponentModule).catch(err => console.log(err))
}
},
];
app.component.html
<code><ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="/remote1">Remote1</a></li>
<router-outlet></router-outlet>
<code><ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="/remote1">Remote1</a></li>
</ul>
Home Works
<router-outlet></router-outlet>
</code>
<ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="/remote1">Remote1</a></li>
</ul>
Home Works
<router-outlet></router-outlet>
When tried running only the remote1 with nx serve remote1 on localhost:4204 and running the angular application with ng serve on localhost:4200
Im getting these 2 errors and remote1 is not getting printed.
Error Typerror: container is undefined
For the first one I tried to add the
<code>scriptType: 'text/javascript'
<code>scriptType: 'text/javascript'
</code>
scriptType: 'text/javascript'
but that section is not available on the remote app created with nx.