Module Federation with Angular: Sharing service from Shell to Remote
For the project setup refer: app
Let's say i have shell and remote right now
With Module federation installed
And Also angular.json updated
shellserv.service.ts
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root' // Ensure the service is available globally
})
export class ShellService {
constructor() {
}
sayHello() {
return "hello from Shell!!"
}
}
Make sure this works in shell app first
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import {ShellService} from './shellserv.service';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
ShellService]
};
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {ShellService} from './shellserv.service';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
providers: [ShellService],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
constructor(private serv: ShellService) {
}
title = 'shell';
ngOnInit() {
console.log(this.serv.sayHello())
}
}
If its fine, add the 'exposes' object in the webpack
shell/webpack.config.ts
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
module.exports = withModuleFederationPlugin({
name: 'shell',
filename: 'remoteEntry.js',
exposes: {
'./SharedService': './src/app/shellserv.service.ts'
},
shared: {
...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
}
});
REMOTE
remote/webpack.config.ts
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
module.exports = withModuleFederationPlugin({
name: 'remote',
filename: 'remoteEntry.js',
exposes: {
'./Component': './src/app/app.component.ts',
},
remotes: {
shell: 'shell@http://localhost:4200/remoteEntry.js'
},
shared: {
...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
},
});
remote/app.component.ts
import { loadRemoteModule } from '@angular-architects/module-federation';
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'remote';
message?: string;
constructor() {
this.loadShellService()
}
async loadShellService() {
try {
const module = await loadRemoteModule({
remoteEntry: 'http://localhost:4200/remoteEntry.js',
type: 'module',
exposedModule: './SharedService'
});
const test = new module.ShellService();
this.message = test.sayHello()
console.log('SharedService Module Loaded:', module);
} catch (error) {
console.error('Error loading SharedService:', error); // Log the actual error
}
}
}
Just to note, this is the router i have (unrelated, just putting it here)
import { loadRemoteModule } from '@angular-architects/module-federation';
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: 'remote',
loadComponent: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:4201/remoteEntry.js',
exposedModule: './Component'
}).then(m => m.AppComponent)
},
];
remote/app.component.html
<h1>hey from remote {{message}}</h1>
<router-outlet />
Comments
Post a Comment