Builder
Reference for runEsBuildBuilder and EsBuildBuilderOptions — the Native Federation esbuild adapter's high-level entry point.
runEsBuildBuilder is the high-level entry point most projects use. It loads federation.config.js, registers the esbuild adapter with the core, runs the initial build, and — when watch is on — keeps a file watcher and rebuild queue running until you call close().
Signature
import { runEsBuildBuilder } from '@softarc/native-federation-esbuild';
const federation = await runEsBuildBuilder(
federationConfigPath: string,
options: EsBuildBuilderOptions,
): Promise<EsBuildBuilder>;
Minimal Call
const federation = await runEsBuildBuilder('federation.config.js', {
outputPath: 'dist',
entryPoints: ['src/bootstrap.tsx'],
});
await federation.close();
Everything else has a sensible default. The only required field is outputPath — the adapter throws [esbuild-builder] outputPath is required if it is missing.
EsBuildBuilderOptions
| Option | Type | Default | Notes |
|---|---|---|---|
outputPath | string | required | Directory that receives remoteEntry.json and the bundled artifacts. |
workspaceRoot | string | process.cwd() | Resolved against cwd(). esbuild runs from this directory, and relative tsConfig, cachePath, outputPath and fileReplacements paths resolve against it. Useful when the build script runs from a monorepo root. |
tsConfig | string | <workspaceRoot>/tsconfig.json if it exists | Resolved against workspaceRoot. Forwarded to esbuild's tsconfig option for the source-code bundle, and the core reads its paths for shared mappings. Without one, esbuild finds the nearest tsconfig.json per file. Point it at tsconfig.base.json when your paths only live there. |
cachePath | string | core default | A relative path is resolved against workspaceRoot; an absolute path is used as-is. Otherwise the core's getDefaultCachePath is used. See Caching. |
projectName | string | — | Forwarded to the core; used for logging and cache scoping in multi-project workspaces. |
entryPoints | string[] | — | Source entries for the federation build. Usually the files referenced by exposes in federation.config.js. |
packageJson | string | — | Path to the project's package.json. Override when it is not next to the federation config. |
dev | boolean | false | Enables sourcemaps and disables minification in both the source-code and node-modules esbuild contexts. Also flips the process.env.NODE_ENV define to "development". |
watch | boolean | false | Starts the file watcher and rebuild queue. The returned federation object stays live until you call close(). |
watchLinkedDeps | boolean | false | In watch mode, also polls shared packages that are npm linked into a checkout outside node_modules, so rebuilding the library rebuilds this app. See Watch Mode. |
watcher | WatchPort['watch'] | Node's fs.watch | Swaps in another watching implementation. |
verbose | boolean | false | Sets the adapter's log level to verbose. Rebuild cancellations, watcher events and full error stacks are logged. |
rebuildDelay | number | 50 (ms) | Debounce before a rebuild fires after a file change. Clamped to a minimum of 10 ms internally. |
cacheExternalArtifacts | boolean | true | Set false to force the core to re-bundle shared node-modules on every build. Only useful when debugging cache issues. |
adapterConfig | EsBuildAdapterConfig | { plugins: [] } | esbuild-specific extension points. See Adapter Configuration. |
Return Value — EsBuildBuilder
interface EsBuildBuilder {
federationInfo: FederationInfo;
externals: string[];
options: NormalizedEsBuildBuilderOptions;
close(): Promise<void>;
}
federationInfo— the result of the last successful build (remote name, exposed modules, shared descriptors, ...). In watch mode this is a live getter — read it whenever you need a fresh snapshot.externals— the list of module names the core marked as shared/external, forwarded to esbuild'sexternal.options— the normalized, fully-defaulted options that were actually used. Handy for logging.close()— tears everything down: cancels any pending rebuild and waits for a running one, stops the watcher, and disposes all esbuild contexts. Calling it more than once is safe. Always call it before exit, even in non-watch mode, so the process can shut down cleanly.
Watch Mode
When watch: true, the adapter:
- Creates an NF file watcher that observes every source file the initial build touched, plus the source directories of your shared mappings — so a file added to a mapped library after the last build is picked up too.
- Queues a rebuild on change. Rebuilds are debounced by
rebuildDelayand serialized through aRebuildQueue— a new change mid-build cancels the in-flight rebuild viaAbortSignalrather than racing it. The changes of a cancelled or failed rebuild carry over into the next one. - Calls
rebuildForFederationon the core, which only re-bundles the entry points whose inputs changed.
A shared package you are developing through npm link sits outside the watched sources. Set watchLinkedDeps: true to have the watcher poll its real directory as well. See Watching npm-linked shared dependencies.
Rebuild outcomes:
- Success — logs
Federation rebuild done.and updatesfederationInfo. - Cancelled — a newer change came in while the previous rebuild was still running. Logged only in
verbosemode. - Error — logs
Federation rebuild failed!. The watcher keeps running; fix the file and the next save triggers another rebuild.
Lower-Level API — createEsBuildAdapter
If you drive buildForFederation / rebuildForFederation yourself (e.g. integrating with a custom dev server or another build tool's lifecycle), skip runEsBuildBuilder and construct just the adapter:
import { createEsBuildAdapter } from '@softarc/native-federation-esbuild';
import { setBuildAdapter, buildForFederation } from '@softarc/native-federation';
const adapter = createEsBuildAdapter({ plugins: [] }, { workspaceRoot: process.cwd() });
setBuildAdapter(adapter);
await buildForFederation(config, normalizedOptions, externals);
await adapter.dispose();
The first argument is the EsBuildAdapterConfig. The optional second argument takes workspaceRoot, the directory esbuild runs from; it defaults to the working directory. runEsBuildBuilder passes its own workspaceRoot here.
createEsBuildAdapter returns an NFBuildAdapter with three methods and an externalsCacheKey (see Shared Packages and the Cache):
setup(name, options)— creates an esbuild context for a single bundle entry, replacing any existing context of that name. Shared packages (options.kind === 'shared') get the node-modules settings; exposed modules and shared mappings get the source-code settings.build(name, { modifiedFiles?, signal? })— rebuilds, writes output files, and returns anNFBuildAdapterResult[]naming each file and the entry it was built from. Aborts cleanly whensignalfires.dispose(name?)— disposes a single context by name, or all contexts when called without arguments.
For 99% of projects, runEsBuildBuilder is the right call. Reach for createEsBuildAdapter only when the core's built-in build loop doesn't fit your workflow.