Skip to the solution
HardFrontend11 min read

How do you handle micro-frontend architecture in Angular using Module Federation?

1.1k views

The problem

Question presented to candidate: "Three teams want to ship parts of our Angular 22 portal independently: a shell, an orders area and a reporting area. How would you structure that as micro-frontends with Module Federation, and what are the trade-offs?"

What a strong answer should cover:

  • Host (shell) and remotes: each remote is built and deployed separately and exposes modules (a component or a routes file); the host loads them at runtime.
  • Two implementations for Angular: webpack Module Federation (@angular-architects/module-federation, needs a webpack builder) and Native Federation (@angular-architects/native-federation, built on the CLI's esbuild builder, ES modules and import maps).
  • Shared dependencies: Angular, RxJS and shared libraries configured as singletons with version rules, so one copy of @angular/core runs.
  • Dynamic remotes via a manifest (federation.manifest.json) so URLs can change per environment without rebuilding the shell; load with loadRemoteModule inside loadComponent/loadChildren.
  • Cross-cutting concerns: routing ownership, communication (URL, custom events, a shared library), design system, auth, and failure handling when a remote is down.
  • Honest trade-offs: team autonomy and independent deploys vs bundle duplication risk, version coordination, and operational complexity; a monorepo with lazy routes is often enough.

Clarifying questions expected:

  • "Do teams need independent deployments, or just independent code ownership?"
  • "Must all parts stay on the same Angular version, or mix versions and frameworks?"
  • "Is SSR required?"

Code / implementation expected: Optional β€” a remote's federation config and a host route that loads an exposed component.

  • architecture
  • micro-frontends

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

11 min read Β· 11 sections

Read the code

AngularRemote: federation.config.mjs generated by the native-federation init schematic, edited to expose ./Orders (built with ng build)
import {
  withNativeFederation,
  fromPackageJson,
} from '@angular-architects/native-federation/config';

export default withNativeFederation({
  name: 'mfe1',

  exposes: {
    './Orders': './src/app/orders.ts',
  },

  shared: fromPackageJson({
    singleton: true,
    strictVersion: true,
    requiredVersion: 'auto',
    build: 'package',
  })
    // includeSecondaries is an opt-out of ignoreUnusedDeps, so all of
    // @angular/core is shared to prevent mismatches.
    .patch(['@angular/core'], { includeSecondaries: { keepAll: true } }),

  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

  features: {
    // ignoreUnusedDeps is enabled by default now
    // ignoreUnusedDeps: true,

    // Opt-in: groups chunks in remoteEntry.json for smaller metadata file
    denseChunking: true,
  },
});
AngularHost: lazy route that loads the remote component via the initFederation result (built with ng build; not run in a browser)
import { Routes } from '@angular/router';
import { federation } from '../federation';

export const routes: Routes = [
  {
    path: 'orders',
    // Resolved at runtime from the manifest, not at build time.
    loadComponent: () =>
      federation
        .then((nf) => nf.loadRemoteModule<typeof import('./orders-types')>('mfe1', './Orders'))
        .then((m) => m.Orders),
  },
];

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 84 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextHard

What are signal inputs and model() in modern Angular?

Continue