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

Popular posts from this blog

Inside the JavaScript Memory Box: Visualizing Variables, References, and Copies

React & State Management: All Concepts

React: Communication between components