TLDR; Native Federation is a framework- and tooling-agnostic implementation of Module Federation. Hence, we don't depend on webpack. This is important in the mid- and long-term to prevent a vender-lockin. In the short term, this allows to get started with modern technologies like esbuild or vite.

Understanding Module Federation

Module Federation significantly simplifies the construction of Micro Frontends and other plugin-oriented architectures. It enables the loading of EcmaScript modules from applications that have been compiled and deployed independently of each other:

Module Federation allows for runtime integration

At present, however, it is largely bound to webpack. This is not a major concern in the short term, and perhaps not even in the medium term, given webpack's widespread adoption.

That said, technologies inevitably evolve. The Angular team, for instance, is currently exploring CLI support for esbuild, which shows great promise in terms of build speed improvements.

This leads to the question of how to apply the proven conceptual framework of Module Federation without relying on webpack, in order to make your Micro Frontend setup ready for the future.

Our solution to this challenge is Native Federation.

Introducing Native Federation

Native Federation is a browser-native approach that functions independently of any particular build tool or framework. Being browser-native means we leverage current and upcoming browser capabilities like EcmaScript Modules and Import Maps.

Our demonstrations make use of the contemporary esbuild bundler, celebrated for its impressive build performance. Certain examples also utilize vite. Other build tools can be incorporated as well through a straightforward adapter mechanism.

Architecture with Distinct Layers

Native Federation is structured into two distinct levels:

Stack

The foundational layer, @softarc/native-federation, also referred to as "Native Federation Core", is not tied to any specific framework or build tool, making it suitable for a wide range of scenarios. To make Native Federation easier to adopt, the layer built on top offers integrations with established ecosystems. For example, we provide an immediate integration for the Angular CLI via @angular-architects/native-federation. Additionally, there is a plugin for vite named @gioboa/vite-module-federation. More integrations can be added as needed.

For frameworks like React or Vue, a deeper integration is currently not necessary. In those situations, working directly with Native Federation Core is quite straightforward.

Aligned with Module Federation Principles

Given that Native Federation embodies the same conceptual model as Module Federation, you can apply your existing knowledge of Module Federation directly. Moreover, the configuration for Native Federation mirrors what you would expect from Module Federation:

// federation.config.js

const {
  withNativeFederation,
  shareAll,
} = require("@softarc/native-federation/build");

module.exports = withNativeFederation({
  name: "remote",

  exposes: {
    "./module": "remote/src/is-long-weekend.ts",
    "./react-remote": "remote/src/react-app.tsx",
  },

  shared: {
    ...shareAll({
      singleton: true,
      strictVersion: true,
      requiredVersion: "auto",
      includeSecondaries: false,
    }),
  },

});

The Core of Native Federation

To begin with Native Federation Core, you only need to incorporate three helper functions into your build process:

import * as esbuild from 'esbuild';
import * as path from 'path';
import * as fs from 'fs';
import { esBuildAdapter } from '@softarc/native-federation-esbuild';
import { federationBuilder } from '@softarc/native-federation/build';

const projectName = 'shell';
const tsConfig = 'tsconfig.json';
const outputPath = dist/${projectName};

/*
 *  Step 1: Initialize Native Federation
*/

await federationBuilder.init({
    options: {
        workspaceRoot: path.join(__dirname, '..'),
        outputPath,
        tsConfig,
        federationConfig: ${projectName}/federation.config.js,
        verbose: false,
    },

    /*
        * As this core lib is tooling-agnostic, you
        * need a simple adapter for your bundler.
        * It's just a matter of one function.
    */
    adapter: esBuildAdapter
});

/*
  * Step 2: Trigger your build process
  *
  * You can use any tool for this. Here, we go 
  * with a very simple esbuild-based build.
  * 
  * Just respect the externals in 
  * federationBuilder.externals.
*/

[...]

await esbuild.build({
    [...]
    external: federationBuilder.externals,
    [...]
});

[...]

/*
  * Step 3: Let the build method do the additional tasks
  *   for supporting Native Federation
*/

await federationBuilder.build();

Using federationBuilder.build will bundle both the shared and exposed portions of your application.

In the example, the esBuildAdapter facilitates using esbuild for tasks internal to Native Federation. For operations that esbuild cannot handle yet, it falls back to rollup. This implementation can be found in our @softarc/native-federation-esbuild package.

Should you prefer a different build tool, you have the option to develop your own adapter for it. Doing so merely requires providing a single function that conforms to our BuildAdapter type definition.

We are excited to announce that Version 1.0 of @softarc/native-federation has been released.

For more details, please check out Native Federation here, which includes both a VanillaJS example and one based on React.

Angular Integration for Native Federation

The @angular-architects/native-federation package offers a smooth integration with the Angular CLI. It leverages an esbuild-based builder and includes schematics to automate routine tasks.

To start, you simply install the package and run its init schematic:

npm i @angular-architects/native-federation -D

ng g @angular-architects/native-federation:init --project shell --type host

Everything else works just like our Module Federation plugin.

If you are eager to try Native Federation for Angular, you can access comprehensive instructions and an example through this link.

Get Started Today!

If this piques your interest, feel free to experiment with Native Federation right now. Explore the resources below and test out the linked examples. We highly value your feedback. Encountering any problems? Please report them on our GitHub page.

Available Resources

The documentation in our package readmes will walk you through using Native Federation. They also reference several examples:

Sample Projects

Acknowledgements

Special thanks go out to:

  • Zack Jackson for initially conceiving the brilliant concept of Module Federation and its successful model
  • Tobias Koppers for his assistance in making Module Federation a core feature of webpack
  • Florian Rappl for engaging discussions on these topics during a speakers dinner in Nuremberg
  • The Nx Team, particularly Colum Ferry, for seamlessly integrating webpack Module Federation into Nx and thus promoting its adoption (Nx + Module Federation === ❤️)
  • Michael Egger-Zikes for his contributions to our Module Federation projects and for offering valuable insights
  • The Angular CLI Team, especially Alan Agius and Charles Lyding, for their efforts on the experimental esbuild builder for Angular
  • Giorgio Boa for creating the excellent vite plugin for module federation.