Migration to v4

Applies to

The steps below cover the framework-agnostic parts of the v3 → v4 upgrade — the two files every Native Federation project owns, regardless of whether it is built with Angular, React, Vite or a custom stack. For Angular-specific changes (builder, schematics, main.ts), see Angular Adapter → Migration to v4.

What changes at this layer: federation.config.js is renamed to federation.config.mjs and switches from CommonJS to ESM, and package.json bumps to the v4 packages. That's it — the file layout is unchanged, and you do not need "type": "module".

1. Clear stale caches

Before the first v4 build, wipe the caches your old build produced. Mixing v3 artifacts with v4 output is the most common source of "it runs but the browser can't find a chunk" errors.

📁 project-root/
├── 📁 dist/                   ← previously bundled artifacts
└── 📁 node_modules/
    └── 📁 .cache/             ← native federation cache

If you use Angular, also remove .angular/.

2. Bump the packages in package.json

Native Federation 4 is fully ESM — both the config file and the emitted artifacts. Update the dependencies to their v4 majors:

{
  "name": "mfe1",
  "version": "1.2.3",
  "dependencies": {
    "@softarc/native-federation-runtime": "~4.0.0"
  },
  "devDependencies": {
    "@softarc/native-federation": "~4.0.0",
    "@softarc/native-federation-orchestrator": "^4.0.0"
  }
}

You do not need to add "type": "module". ESM comes from renaming the config to federation.config.mjs (next step) — Node treats .mjs as a module regardless of the package-wide setting, so the rest of your project is left untouched. Setting "type": "module" is optional and only matters if you want the whole workspace to default to ESM.

3. Convert federation.config.js to ESM:

The config shape is the same as in v3. Only the module syntax changes: require(...) becomes import, and module.exports becomes export default. Also the file name changes to federation.config.mjs.

Before (v3, CommonJS)

const { withNativeFederation, share, shareAll } = require('@softarc/native-federation/config');

module.exports = withNativeFederation({
  name: 'mfe1',

  exposes: {
    './Component': './src/bootstrap.ts',
  },

  shared: {
    ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
    ...share({ '@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' } }),
  },

  skip: [
    'rxjs/ajax',
    'rxjs/fetch',
    'rxjs/testing',
    'rxjs/webSocket',
  ],
});

After (v4, ESM)

import { withNativeFederation, shareAll } from '@softarc/native-federation/config';

export default withNativeFederation({
  name: 'team/mfe1',

  exposes: {
    './Component': './src/bootstrap.ts',
  },

  shared: {
    // shareAll still works. In v4 you can also merge per-package overrides
    // straight into the shareAll call — no need for a trailing share(...).
    ...shareAll(
      { singleton: true, strictVersion: true, requiredVersion: 'auto' },
      {
        overrides: {
          '@angular/core': {
            singleton: true,
            strictVersion: true,
            requiredVersion: 'auto',
            includeSecondaries: { keepAll: true },
          },
        },
      },
    ),
  },

  skip: ['rxjs/ajax', 'rxjs/fetch', 'rxjs/testing', 'rxjs/webSocket'],

  features: {
    ignoreUnusedDeps: true, // on by default in v4
    denseChunking: true,    // opt-in: groups chunks in remoteEntry.json for smaller payloads
  },
});

The features block is new in v4. See Configuration → Feature Flags for the full list.

4. Adopt the Orchestrator (recommended)

The Orchestrator@softarc/native-federation-orchestrator — is now stable and is the recommended browser runtime for v4 hosts. It speaks the same remoteEntry.json contract as the default @softarc/native-federation-runtime, so remotes built by the Core work unchanged. On top of that it adds:

Switching is an install + import change on the host; the emitted artifacts stay the same. The exact host bootstrap code depends on your framework — see the Orchestrator overview for configuration options, or Angular Adapter → Runtime for the Angular-specific bootstrap.

SSR note. The Orchestrator is client-side only today. If you need remote modules to execute during server-side rendering, keep using the default Runtime on the SSR path.

That's it

With the two files above updated and caches cleared, your project builds and runs on Native Federation 4. If something broke along the way, please open an issue — we want to hear about it.

Where to Go Next