Custom Builder

Applies to

Sometimes you need an esbuild plugin in the federation build itself — code transformation, bundling tweaks, third-party tooling. Since v4 the Angular adapter exposes its builder factory as runBuilder from @angular-architects/native-federation-v4/internal, so you can wrap it in your own Architect builder and pass extra plugins through.

The Pattern

  1. Write a tiny builder file that calls runBuilder with an extended options object.
  2. Point the relevant angular.json targets at your wrapper instead of the default @angular-architects/native-federation-v4:build.

1. The wrapper

// custom-builder.js
import { runBuilder } from '@angular-architects/native-federation-v4/internal';
import { createBuilder } from '@angular-devkit/architect';
import { myEsbuildPlugin } from './my-esbuild-plugin.js';

async function* customBuilder(options, context) {
  const nfOptions = {
    ...options,
    plugins: [
      myEsbuildPlugin(),
      // ...more plugins
    ],
  };

  yield* runBuilder(nfOptions, context);
}

export default createBuilder(customBuilder);

The plugins array is appended to the adapter's own externals plugin, so the order is: externals plugin first, then yours. Plugins receive the standard esbuild PluginBuild interface and run for both the federation build (shared bundles, exposed modules) and the Angular build path.

2. Wire it in angular.json

{
  "projects": {
    "mfe1": {
      "architect": {
        "build": {
          "builder": "./custom-builder",
          "options": {
            "projectName": "mfe1",
            "tsConfig": "projects/mfe1/tsconfig.federation.json"
            // ... everything you'd normally pass to the federation builder
          }
        },
        "serve": {
          "builder": "./custom-builder",
          "options": { /* same idea */ }
        }
      }
    }
  }
}

You're swapping the builder, not the options schema — every option from Builder → Options still applies.

Notes

Related