I have just study micro frontend with Angular by native federation. I 've just done in create host app (shell) and remote app (vehicle, ...); configured port for host and remote apps . I was configuring routes to make host app approach remote app but I have some problems. When I enter host link (http://localhost:4200), I can't see remote app that I want to appear, but when I enter remote app link (http://localhost:4201/), It worked smoothly. I use console.log to check what happened and I saw that when I use host link, It went to app.ts of remote app, went to html file of that remote app but couldn't use of that remote app. As I said, when I ran by remote app link, everything worked. Here are some file in my project. Please help me do this. Thanks. There are some files in host app (shell): federation.manifest.json file: { "vehicle": "http://localhost:4201/remoteEntry.json", "manufacturer": "http://localhost:4202/remoteEntry.json", "management-unit": "http://localhost:4203/remoteEntry.json", "driver": "http://localhost:4204/remoteEntry.json" } main.ts file: import { initFederation } from '@angular-architects/native-federation'; import { initializeKeycloak } from '@keycloak/keycloak-init'; initializeKeycloak() .then(() => { initFederation('federation.manifest.json') .catch(err => console.error(err)) .then(_ => import('./bootstrap')) .catch(err => console.error(err)); }); bootstrap.ts file: import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { App } from './app/app'; bootstrapApplication(App, appConfig) .catch((err) => console.error(err)); index.html file: <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Vehicle Management</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-shell-root></app-shell-root> </body> </html> app.html file: <app-shell-header></app-shell-header> <div class="content"> <router-outlet /> </div> app.ts file: import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { Header } from './header/header'; @Component({ selector: 'app-shell-root', standalone: true, imports: [RouterOutlet, Header], templateUrl: './app.html', styleUrl: './app.css' }) export class App { protected title = 'Vehicle Management'; } app.routes.ts file: import { loadRemoteModule } from '@angular-architects/native-federation'; import { Routes } from '@angular/router'; import { authGuard } from '@keycloak/keycloak-auth.guard'; export const routes: Routes = [ { path: '', loadComponent: () => loadRemoteModule('vehicle', './Component').then((m) => m.App), canActivate: [authGuard], }, { path: 'vehicle', loadComponent: () => loadRemoteModule('vehicle', './Component').then((m) => m.App), }, { path: 'manufacturer', loadComponent: () => loadRemoteModule('manufacturer', './Component').then((m) => m.App), }, { path: 'management-unit', loadComponent: () => loadRemoteModule('management-unit', './Component').then((m) => m.App), }, { path: 'driver', loadComponent: () => loadRemoteModule('driver', './Component').then((m) => m.App), }, { path: '**', component: Headers }, ]; app.config.ts file: import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes) ] }; There are some files in remote app (vehicle): vehicle.component.ts file: import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { ManufacturerItems } from '@vehicle/types/ManufacturerItems'; import { VehicleItems } from '@vehicle/types/VehicleItems' import { CommonModule, DatePipe } from '@angular/common'; import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { keycloak } from '@keycloak/keycloak-init'; import * as XLSX from 'xlsx'; import { jsPDF } from 'jspdf'; import autoTable from 'jspdf-autotable'; import '@vehicle/assets/fonts/roboto-font'; import { VehicleServices } from '@vehicle/services/VehicleServices'; import { ManufacturerServices } from '@vehicle/services/ManufacturerServices'; import { Subject, takeUntil } from 'rxjs'; @Component({ selector: 'vehicle-app', standalone: true, imports: [ CommonModule, ReactiveFormsModule, FormsModule ], templateUrl: './vehicle.component.html', styleUrl: './vehicle.component.css' }) export class VehicleComponent { private destroy$ = new Subject<void>(); constructor( private vehicleServices: VehicleServices, private manufacturerServices: ManufacturerServices, private router: Router ) { console.log('✅ VehicleComponent đã được load'); } vehicles: VehicleItems[] = []; manufacturers: ManufacturerItems[] = []; licensePlateKey = new FormControl(''); manufacturerId = new FormControl(''); currentPage: number = 0; pageSize: number = 10; totalItems: number = 0; totalPages: number = 0; ngOnInit(): void { this.loadVehicles(); this.manufacturerServices.getAllManufacturers() .pipe(takeUntil(this.destroy$)) .subscribe((manufacturers: ManufacturerItems[]) => { this.manufacturers = manufacturers; }); } loadVehicles() { this.vehicleServices.getAllVehicles(this.currentPage, this.pageSize) .pipe(takeUntil(this.destroy$)) .subscribe({ next: (response: any) => { this.vehicles = response.content; console.log(this.vehicles); this.totalItems = response.totalElements; this.totalPages = response.totalPages; }, error: (err) => { console.error('Error loading vehicles:', err); } }); } handleSearchVehicle() { this.vehicleServices.searchVehicles( this.licensePlateKey.value as string, Number(this.manufacturerId.value), this.currentPage, this.pageSize ) .pipe(takeUntil(this.destroy$)) .subscribe({ next: (response: any) => { this.vehicles = response.content; this.totalItems = response.totalElements; this.totalPages = response.totalPages; }, error: (err) => { console.error('Error searching vehicles:', err); } }); } goToPage(page: number): void { if (page < 0 || page >= this.totalPages) return; this.currentPage = page; if (this.isSearchActive()) { this.handleSearchVehicle(); } else { this.loadVehicles(); } } changePageSize(size: number): void { this.pageSize = size; this.currentPage = 0; if (this.isSearchActive()) { this.handleSearchVehicle(); } else { this.loadVehicles(); } } // Check if search is active isSearchActive(): boolean { return !!this.licensePlateKey.value || this.manufacturerId.value !== '0'; } // Generate page numbers for pagination controls getPagesArray(): number[] { const pages = []; const maxVisiblePages = 5; let startPage = Math.max(0, this.currentPage - Math.floor(maxVisiblePages / 2)); let endPage = Math.min(this.totalPages - 1, startPage + maxVisiblePages - 1); // Adjust if we're at the beginning if (endPage - startPage + 1 < maxVisiblePages) { startPage = Math.max(0, endPage - maxVisiblePages + 1); } for (let i = startPage; i <= endPage; i++) { pages.push(i); } return pages; } viewUpdateForm(vehicleId: number) { this.router.navigate(['/vehicles/update', vehicleId]); } viewAddForm() { this.router.navigate(['/vehicles/add']); } confirmDelete(vehicleId: number) { if (confirm('Are you sure?')) { this.vehicleServices.deleteVehicles(vehicleId) .pipe(takeUntil(this.destroy$)) .subscribe({ next: () => { alert('Vehicle Deleted !'); this.loadVehicles(); }, error: (err) => { if (err.status === 401) { alert("Your session has expired. Please log in again."); keycloak.logout({ redirectUri: window.location.origin }); } } }); } } //download file exportXLSXFile() { this.vehicleServices.getVehiclesList() .pipe(takeUntil(this.destroy$)) .subscribe((data: any[]) => { const worksheetData = [ ['CÔNG TY TNHH ABC XYZ'], ['BẢNG THEO DÕI DANH SÁCH XE'], [], ['ID', 'License Plate', 'Manufacturer', 'Management Unit', 'Driver', 'Created Time', 'Updated Time'], ...data.map(v => [ v.id, v.licensePlate, v.manufacturerName, v.managementUnitName, v.driverName, v.createdTime, v.updatedTime ]), [], ['', '', '', '', '', 'Giám đốc xác nhận'] ]; const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(worksheetData); ws['!merges'] = [ { s: { r: 0, c: 0 }, e: { r: 0, c: 6 } }, { s: { r: 1, c: 0 }, e: { r: 1, c: 6 } } ]; ws['!cols'] = [ { wch: 5 }, // ID { wch: 15 }, // License Plate { wch: 20 }, // Manufacturer { wch: 25 }, // Management Unit { wch: 20 }, // Driver { wch: 20 }, // Created Time { wch: 20 }, // Updated Time ]; const wb: XLSX.WorkBook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, 'Vehicle Report'); XLSX.writeFile(wb, 'vehicle-report.xlsx'); }); } exportPDFFile() { this.vehicleServices.getVehiclesList() .pipe(takeUntil(this.destroy$)) .subscribe((vehicles: VehicleItems[]) => { const doc = new jsPDF(); doc.setFont('Roboto', 'normal'); doc.setFontSize(14); doc.text('CÔNG TY TNHH ABC XYZ', 105, 15, { align: 'center' }); doc.setFontSize(16); doc.text('BẢNG THEO DÕI DANH SÁCH XE', 105, 25, { align: 'center' }); const date = new DatePipe('en-US').transform(new Date(), 'dd/MM/yyyy'); doc.setFontSize(12); doc.text(`Ngày xuất: ${date}`, 14, 35); autoTable(doc, { startY: 40, head: [['ID', 'License Plate', 'Manufacturer', 'Management Unit', 'Driver', 'Created Time', 'Updated Time']], body: vehicles.map(v => [ v.id, v.licensePlate, v.manufacturerName, v.managementUnitName, v.driverName, v.createdTime, v.updatedTime ]), styles: { font: 'Roboto', fontSize: 10, fontStyle: 'normal' }, headStyles: { fillColor: [41, 128, 185] }, }); const finalY = (doc as any).lastAutoTable.finalY + 20; doc.text('Giám đốc xác nhận', 180, finalY, { align: 'right' }); doc.save('vehicle-report.pdf'); }); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); console.log('Component destroyed and subscriptions cleaned up'); } } app.routes.ts file: import { Routes } from '@angular/router'; import { authGuard } from '@keycloak/keycloak-auth.guard'; import { VehicleComponent } from './pages/vehicle/vehicle.component'; import { UpdateVehicleComponent } from './pages/updateVehicle/updateVehicle.component'; import { AddVehicleComponent } from './pages/addVehicle/addVehicle.component'; import { App } from './app'; export const routes: Routes = [ { path: '', canActivate:[authGuard], component: VehicleComponent, }, { path: 'vehicles/update/:id', component: UpdateVehicleComponent }, { path: 'vehicles/add', component: AddVehicleComponent } ]; app.ts file: import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-vehicle-root', standalone: true, imports: [RouterOutlet], templateUrl: './app.html', styleUrl: './app.css', }) export class App { protected title = 'Vehicle'; constructor() { console.log('✅ AppComponent load'); } } ` federation.config.js file: ` const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config'); module.exports = withNativeFederation({ name: 'vehicle', exposes: { './Component': './projects/vehicle/src/app/app.ts', }, shared: { ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), }, skip: [ 'rxjs/ajax', 'rxjs/fetch', 'rxjs/testing', 'rxjs/webSocket', // Add further packages you don't need at runtime ] // Please read our FAQ about sharing libs: // https://shorturl.at/jmzH0 }); bootstrap.ts file: import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { App } from './app/app'; bootstrapApplication(App, appConfig) .catch((err) => console.error(err)); app.config.ts file: import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { AuthInterceptor } from '@keycloak/auth.interceptor' import { routes } from './app.routes'; import { provideHttpClient, withInterceptors } from '@angular/common/http'; console.log('app.config.ts của remote !!!!'); export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter( routes ), provideHttpClient(withInterceptors([AuthInterceptor])) ] }; main.ts file: import { initFederation } from '@angular-architects/native-federation'; import { initializeKeycloak } from '@keycloak/keycloak-init'; initializeKeycloak() .then(() => { initFederation() .catch(err => console.error(err)) .then(_ => import('./bootstrap')) .catch(err => console.error(err)); }); app.html file: <router-outlet></router-outlet> host app runs smoothly like what remote app did Continue reading...