Build Process
The federationBuilder object is the entry point for the
core build. It wraps the underlying steps (normalize config, compute
externals, bundle shared and exposed modules, write artifacts) behind
three methods: init, build,
close.
Lifecycle Overview
-
init(params)— load and normalizefederation.config.js, register the bundler adapter, decide which packages are externals, and attach a federation cache. Exposes theexternalslist so your bundler step can exclude them. -
Your own bundler step — compile your application entry
points. Pass
federationBuilder.externalsas externals so shared packages aren't inlined. -
build(opts?)— bundle every shared external (once, with caching), every shared mapped path, and every exposed module, then writeremoteEntry.jsonand the import map. When called again on the same builder instance it performs an incremental rebuild. -
close()— dispose the underlying adapter (closes contexts, stops watchers, flushes caches).
Minimal Example
import * as esbuild from 'esbuild';
import * as path from 'path';
import { esBuildAdapter } from '@softarc/native-federation-esbuild';
import { federationBuilder } from '@softarc/native-federation';
await federationBuilder.init({
options: {
workspaceRoot: path.join(__dirname, '..'),
outputPath: 'dist/shell',
tsConfig: 'tsconfig.json',
federationConfig: 'shell/federation.config.js',
verbose: false,
},
adapter: esBuildAdapter,
});
await esbuild.build({
entryPoints: ['shell/main.ts'],
outdir: 'dist/shell',
bundle: true,
format: 'esm',
external: federationBuilder.externals,
});
await federationBuilder.build();
await federationBuilder.close();
The FederationOptions Object
| Field | Type | Required | Description |
|---|---|---|---|
workspaceRoot |
string |
yes | Absolute path to the monorepo / workspace root. All other paths are resolved against it. |
outputPath |
string |
yes |
Directory for federation artifacts (shared bundles,
remoteEntry.json, import map).
|
federationConfig |
string |
yes |
Path (relative to workspaceRoot) to
federation.config.js.
|
projectName |
string |
no |
Overrides the project name used for cache isolation. Defaults
to the name field of the federation config.
|
tsConfig |
string |
no |
Path to tsconfig.json. Used to resolve mapped
paths.
|
packageJson |
string |
no |
Override the package.json used by
shareAll for dependency discovery.
|
entryPoints |
string[] |
no |
Additional entry points considered when
ignoreUnusedDeps is enabled. Defaults to the
values of exposes.
|
dev |
boolean |
no | Development mode — influences bundling and enables the build-notifications endpoint. |
watch |
boolean |
no | Hint to the adapter that it should set up watch mode. |
verbose |
boolean |
no | Verbose logging. |
cacheExternalArtifacts |
boolean |
no |
Cache built shared externals across builds (default
true).
|
buildNotifications |
BuildNotificationOptions |
no | Configures the dev-only notification endpoint that tells the runtime to reload on rebuild. |
SRI hashes are configured under
features.integrityHashesinfederation.config.js— see Feature Flags.
Incremental Builds
The first call to federationBuilder.build() performs a
full build. Every subsequent call on the same builder instance is
treated as a rebuild and only re-runs what has changed:
// initial build
await federationBuilder.build();
// file-change notification from your watcher
await federationBuilder.build({
modifiedFiles: ['/abs/path/to/mfe1/component.ts'],
signal: abortController.signal,
});
Rebuilds reuse the federation cache — already-bundled shared externals
are skipped unless their checksum changes. Pass an
AbortSignal to cancel a build mid-flight (e.g. when a
newer file change arrives).
Caching Shared Externals
Shared externals are the slowest part of a federation build, so the
core caches them by default under
node_modules/.cache/native-federation/<projectName>. On a cache hit the build adapter is never invoked for that bundle —
the outputs are copied from the cache and their metadata is merged
into remoteEntry.json.
-
Disable it with
cacheExternalArtifacts: falseonFederationOptions. -
Supply your own cache via
normalizeFederationOptions(options, cache)orcreateFederationCache(path, bundlerCache?).
For the full mechanics — what counts as a cache hit, the checksum format, the cache layout, how to invalidate it — see Caching.
Accessors on federationBuilder
| Accessor | Available after | Description |
|---|---|---|
externals |
init |
Array of package names to pass as external to
your bundler.
|
config |
init |
The normalized federation config. |
federationInfo |
build |
The last FederationInfo object that was written
to remoteEntry.json.
|
Dev-mode Build Notifications
When dev: true and
buildNotifications.enable: true, the core writes a
buildNotificationsEndpoint into
remoteEntry.json. The runtime subscribes to that endpoint
and triggers a refresh when a rebuild finishes, giving you a fast
HMR-like experience without rebuilding the host.
What Happens Inside build()
Under the hood, build() runs three phases (logged
verbosely when verbose: true):
-
Shared externals —
bundleSharedgroups shared packages byplatform(browser / node) and bybuildmode (default,separate,package). Each group is bundled via the adapter and cached. -
Exposed modules & mapped paths —
bundleExposedAndMappingsbundles everyexposesentry plus every shared mapped path from yourtsconfig. -
Artifact writing —
writeFederationInfoemitsremoteEntry.json;writeImportMapemits the import map the runtime consumes.
See Build Artifacts for the shape of the generated files.