SSR and Hydration with Native Federation for Angular

  1. Micro Frontends with Modern Angular – Part 1: Standalone and esbuild
  2. Micro Frontends with Modern Angular – Part 2: Multi-Version and Multi-Framework Solutions with Angular Elements and Web Components
  3. Combining Native Federation and Module Federation
  4. SSR and Hydration with Native Federation for Angular

Beginning with version 18.2.3, @angular-architects/native-federation supports SSR and all the new hydration features modern Angular provides. It's a feature implemented for version 19 that was back-ported to 18. In this short article, I show how to use this possibility, which is vital for public portals and shops.

📂 Source Code

Example

As usual, the example contains a shell that loads a simple micro frontend. Both -- the micro frontend inside the shell -- is rendered on the server side:

Credits

Server-side Native Federation involves leveraging Import Maps on the server side. For this, the shown implementation uses a fork of Joel Denning's package node-loader/import-maps. Hence, all credits for this part go to Joel who constantly comes up with new ideas for improving the space of Micro Frontends.

Adding SSR and Native Federation to a Project

If @angular/ssr is added before Native Federation, the ng-add schematic provided by Native Federation will integrate both mechanisms with each other. The following commands assume an Angular workspace with a shell and a mfe1 project:

# Add Micro Frontend
ng add @angular/ssr --project mfe1
ng add @angular-architects/native-federation --project mfe1 --type remote --port 4201

# Add Shell
ng add @angular/ssr --project shell
ng add @angular-architects/native-federation --project shell --type dynamic-host --port 4200

If Native Federation is already added, it can be temporarily removed to make sure the ng-add schematics provided by @angular/ssr work as expected:

# Remove Micro Frontend and Shell
ng g @angular-architects/native-federation:remove --project mfe1
ng g @angular-architects/native-federation:remove --project shell

# Add Micro Frontend
ng add @angular/ssr --project mfe1
ng add @angular-architects/native-federation --project mfe1 --type remote --port 4201

# Add Shell
ng add @angular/ssr --project shell
ng add @angular-architects/native-federation --project shell --type dynamic-host --port 4200

What Does the Schematic Generate?

Besides the usual tasks, Native Federation's ng-add schematic updates the server.ts in an SSR project:

import { initNodeFederation } from '@softarc/native-federation-node';

console.log('Starting SSR for Shell');

(async () => {

  await initNodeFederation({
    remotesOrManifestUrl: '../browser/federation.manifest.json',
    relBundlePath: '../browser/',
 });

  await import('./bootstrap-server');

})();

This code initializes Federation on the server side. Then, it delegates to the file bootstrap-server.ts, which starts the server with the same code usually found in server.ts.

Besides this, the default port used is updated to the one passed to --port when ng add was called. Also, it adds CORS support.

Limitation for ng serve

For technical reasons, ng serve only loads the micro frontend into the shell on the client side. A production build created with ng build, however, renders everything on the server side, too.

To prevent server-side errors when running ng serve, the code should provide a server-side fallback for the loaded Micro Frontend. For this, loadRemoteModule now contains a fallback property:

import { Routes } from '@angular/router';
import { loadRemoteModule } from '@angular-architects/native-federation';
import { DummyComponent } from './dummy/dummy.component';
import { HomeComponent } from './home/home.component';

export const routes: Routes = [
 {
        path: '',
        pathMatch: 'full',
        component: HomeComponent
 },
 {
        path: 'mfe1',
        loadComponent: () => loadRemoteModule({
            remoteName: 'mfe1',
            exposedModule: './Component',
            fallback: DummyComponent
 })
 }
];

The fallback can, for instance, be a component with an empty template or a routing configuration with a catch-all route pointing to such a component.

We will try to remove this limitation. However, it should not be a massive show-stopper as SSR is first and foremost needed in production, and developers usually work mainly on their micro front end. Also, providing a fallback makes sense anyway.

Only SSR for Shell Needed

While one can totally activate SSR and hydration for both, the shell and the Micro Frontends, in many cases the latter one can be skipped -- especially if the users always load the Micro Frontends via the shell. Even if the Micro Frontend itself does not use SSR, the shell will render it on the server side. This simplifies the entire solution.

Conclusion

Beginning with version 18.2.3, @angular-architects/native-federation supports SSR. If the ng-add schematic detects an SSR project, it updates the server-side code automatically.

More on this: Angular Architecture Workshop (online, interactive, advanced)

Become an expert for enterprise-scale and maintainable Angular applications with our Angular Architecture workshop!

English Version | German Version

eBook: Micro Frontends and Moduliths with Angular

Lernen Sie, wie Sie große und langfristig wartbare Unternehmenslösungen mit Angular planen und umsetzen

✓ 20 Kapitel
✓ Quellcode-Beispiele
✓ PDF, epub (Android und iOS) und mobi (Kindle)

Gratis downloaden