Adapter Configuration

Applies to

EsBuildAdapterConfig is the esbuild-specific extension point. You pass it as adapterConfig on runEsBuildBuilder (or directly into createEsBuildAdapter). Four fields — all optional except plugins — control extra esbuild plugins, framework presets, entry-point rewriting, and custom file loaders.

Shape

import type * as esbuild from 'esbuild';

export interface EsBuildAdapterConfig {
  plugins: esbuild.Plugin[];
  fileReplacements?: Record<string, string | { file: string }>;
  loader?: { [ext: string]: esbuild.Loader };
  frameworks?: NfFrameworkPlugin[];
}

plugins

Extra esbuild plugins. They are applied to both esbuild contexts — the source-code bundle (your exposed modules and their local source files) and the node-modules bundle (shared dependencies). Use it for the usual esbuild extensions: Sass, CSS modules, SVGR, a GraphQL loader, etc.

import { sassPlugin } from 'esbuild-sass-plugin';

adapterConfig: {
  plugins: [sassPlugin()],
}

Plugins contributed by a framework preset (via its esbuildPlugins) are prepended to this list, so framework plugins run before your own.

fileReplacements

Rewrites the entry-point path of a shared dependency before esbuild sees it. The key is a string that will be matched as a regex against the end of the path; the value is either a target path string, or a { file: string } object (the two forms are equivalent — strings are normalized to the object form internally).

adapterConfig: {
  plugins: [],
  fileReplacements: {
    'node_modules/react/index.js':
      'node_modules/react/cjs/react.production.min.js',
  },
}

Path separators are normalized to forward slashes before matching, so the same config works on Windows.

Typical uses:

frameworks

A list of framework presets (NfFrameworkPlugin[]). Each preset bundles the esbuild settings a framework needs — file replacements, extra resolveExtensions, loaders, esbuild plugins, and whether the CommonJS interop plugin is required for the node-modules bundle.

If you omit frameworks entirely, the adapter applies the built-in React preset (reactFrameworkPlugin()) by default, so existing React setups keep working unchanged. Pass an empty array to opt out of all presets:

import { reactFrameworkPlugin } from '@softarc/native-federation-esbuild/frameworks/react';

adapterConfig: {
  plugins: [],
  frameworks: [reactFrameworkPlugin()], // optional — this is the default
}
adapterConfig: {
  plugins: [],
  frameworks: [], // disable the default React preset
}

A preset is a plain object implementing NfFrameworkPlugin:

Field Type Purpose
name string Identifier for the framework — used in logs/debugging.
fileReplacements { dev?, prod? } Maps of <source path> → <replacement file> applied to node-module entry points. The right map is picked automatically from the build's dev flag.
resolveExtensions string[] Extra esbuild resolveExtensions (e.g. ['.vue']). Merged with the adapter's defaults.
loader Record<string, esbuild.Loader> esbuild loader overrides. Merged with config.loader; your own entries win.
esbuildPlugins esbuild.Plugin[] Framework-specific esbuild plugins. Prepended to config.plugins.
needsCommonJsPlugin boolean Set true when the framework's runtime ships CommonJS (React). Triggers @chialab/esbuild-plugin-commonjs for the node-modules bundle.

A minimal custom preset:

import type { NfFrameworkPlugin } from '@softarc/native-federation-esbuild';
import vuePlugin from 'esbuild-plugin-vue3';

export function vueFrameworkPlugin(): NfFrameworkPlugin {
  return {
    name: 'vue',
    esbuildPlugins: [vuePlugin()],
    resolveExtensions: ['.vue'],
    needsCommonJsPlugin: false,
  };
}

When you supply multiple presets their contributions are merged. Your own top-level EsBuildAdapterConfig keys (plugins, fileReplacements, loader) take precedence over what a preset supplies. See React & CommonJS Interop for how the React preset works in practice.

loader

Passed straight through to esbuild.context()'s loader option for both bundles. Map file extensions to esbuild's built-in loaders ('file', 'dataurl', 'text', 'binary', 'json', 'copy', …):

adapterConfig: {
  plugins: [],
  loader: {
    '.svg': 'dataurl',
    '.png': 'file',
  },
}

What the Adapter Sets for You

A few esbuild options are fixed by the adapter and cannot be overridden through EsBuildAdapterConfig. They are:

esbuild option Value Why
bundle true Federation artifacts must be self-contained.
format 'esm' The runtime loads remotes as ES modules via the import map.
platform 'browser' or 'node' Derived from the core's platform detection (see Build Process).
target ['esnext'] Source-code bundle only. Downlevel in your own toolchain if needed.
splitting false Splitting is not yet supported; every entry is one file.
write false The adapter writes files itself, so it can hash names and feed them to the federation cache.
entryNames '[name]-[hash]' / '[name]' Hashed when the core asks for hashed output, plain otherwise.
resolveExtensions .ts .tsx .mjs .js .cjs (source) / .mjs .js .cjs (node-modules) TypeScript is only resolved in the source-code bundle. Framework presets can add more (e.g. .vue).
external from the core All shared dependencies are marked external so they load via the import map.
sourcemap / minify from dev dev: true enables sourcemaps and disables minification.

Everything else flows from EsBuildAdapterConfig — extra plugins, framework presets, replaced entry paths, and custom loaders.