You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracking issue for the experimental remote builder (formerly build-slim) and its road to feature-parity with Angular's @angular/build:application builder.
Rename: the builder is now registered as remote (was build-slim). Source moved to packages/angular/src/builders/remote/.
What is the remote builder?
A micro-frontend remote builder that runs only the Native Federation build (buildForFederation) and skips Angular's main buildApplication / serveWithVite pipeline entirely. It produces just the federation artifacts (exposes + shared + chunks). It does not serve them — dev serving is external (the host's dev server or any static file server). In watch mode it rebuilds artifacts to disk on change. The remote runs inside a host shell that owns polyfills, the index document, and bootstrapping.
Source: packages/angular/src/builders/remote/
What it already does (via the NF esbuild adapter)
buildForFederation drives the NF esbuild adapter (createAngularEsbuildContext), which already covers:
Angular AOT compilation
Component-level stylesheets (Sass / Less / Tailwind / PostCSS)
Inline-font optimization for component styles
Source maps (sourceMap)
fileReplacements
Browserslist target resolution
Advanced optimization + minification (gated on dev)
Everything Angular's @angular/build:application does in the execute-build / execute-post-bundle / setup-bundling layer is currently absent. Grouped by priority.
A. Output-correctness gaps that matter for a remote
i18n / $localize (build-slim: i18n / $localize support #67) — the linker plugin never runs and inlineI18n is never called, so $localize markers survive raw in output. No localize, i18nMissingTranslation, i18nDuplicateTranslation.
define — custom global constant replacement (adapter currently hardcodes only ngDevMode / ngJitMode).
loader — per-extension esbuild loaders; the adapter reads builderOptions.loader but the builder never sets it.
outputHashing — no configurable cache-busting mode.
conditions / allowedCommonJsDependencies — custom resolution conditions and CommonJS allow-list warnings not forwarded.
Budgets (checkBudgets) — no bundle-size enforcement.
Subresource Integrity (subresourceIntegrity).
Chunk optimization (Rollup/Rolldown pass) — ships esbuild's raw chunking.
Build-stats logging (logBuildStats + estimated transfer sizes) — no per-file size table.
C. Host-owned / by-design omissions
These are legitimately the host's responsibility for a remote — tracked so the decision is explicit, not silent.
HTML / index.html — host-owned by design. The remote builder writes/copies noindex.html (removal done: index-html.ts deleted, index schema option removed); output is strictly the federation artifacts (remoteEntry.json + referenced files) plus copied assets. Angular's index generation (script/style tag injection, preload/modulepreload/preconnect hints, CSP, baseHref / deployUrl rewriting) is also out of scope — the host owns the document and bootstraps the remote.
Polyfills — host-owned by design. Shared runtime polyfills (zone.js, @angular/localize/init) must load once in the host as singletons; bundling them in a remote would double-load zone.js and contradicts the runtime-$localize loading model in build-slim: i18n / $localize support #67. A remote that needs a remote-specific polyfill can import it directly in an exposed entry (it runs on module load), so no polyfills builder option is planned.
Global styles (styles[]) — host owns global styling; only inline component styles are bundled. No styles option.
Global scripts (scripts[]) — host owns global scripts. No scripts option.
Service worker (ngsw.json).
SSR / prerender / appShell / outputMode / server — irrelevant to a CSR remote.
webWorkerTsConfig — web-worker bundling.
security.allowedHosts / autoCsp.
Dev server / serving — removed by design. The builder produces artifacts only (in watch mode it rebuilds to disk on change); serving in dev is external — the host's dev server or any static file server pointed at the output dir. Removed the Vite server (vite-server.ts), the static middleware (static-middleware.ts), and the SSE build-notifier wiring; dropped the port and buildNotifications options. (vite stays a package dependency — still used by the full build builder's plugin path.) Consequently HMR / live-reload, ssl/proxy/host/allowedHosts dev-server options, and CORS handling are out of scope — they belong to whatever serves the remote.
npm-link browser reload gap (npm link + shared libraries stale federation rebuilds and no browser reload in local dev (NF v4 / Angular 21) #55): as of PR fix: Added support for npm link #93 the remote's watcher now tracks npm-link'd shared-package dirs (linkedSharedDirs fed as the 3rd arg to syncNfFileWatcher), so a save inside a linked shared lib does re-bundle fresh federation artifacts to disk in watch mode. But with no dev server / SSE notifier here, the browser is never told to reload — a linked shared-lib change served through a remote still needs a manual refresh. This is consistent with the design above (reload belongs to whatever serves the remote); it's called out so the gap is explicit rather than surprising. See the follow-up below.
Priorities
Highest-value items for remotes specifically: i18n (A), define / loader passthrough (A), and license extraction (B). Category C is host-owned and stays out of the remote builder by design.
Sub-tasks / follow-ups
build-slim: i18n / $localize support #67 — i18n / $localize support: runtime $localize with the host providing translations, plus a self-describing i18n-manifest.json next to remoteEntry.json (option 2). Full design notes & task checklist there.
Watch linked (symlinked) shared-package dirs under node_modules (3-arg syncNfFileWatcher).
Cache invalidation / re-bundle of the affected shared external on a linked-lib change (via rebuildForFederation with realpath'd changedFiles).
Deferred for the remote builder (a linked-lib edit re-bundles to disk but the browser is not reloaded):
Browser auto-reload after a remote rebuild. The build (shell) builder broadcasts an SSE completion event; the remote has no dev server / notifier (Category C), so remote-served linked-lib edits need a manual refresh. A fix would require the remote to signal whatever serves it — e.g. a cross-process reload hook / ping to the host dev server, or a per-remote reload endpoint — rather than reintroducing an in-process SSE server.
Tracking issue for the experimental
remotebuilder (formerlybuild-slim) and its road to feature-parity with Angular's@angular/build:applicationbuilder.What is the
remotebuilder?A micro-frontend remote builder that runs only the Native Federation build (
buildForFederation) and skips Angular's mainbuildApplication/serveWithVitepipeline entirely. It produces just the federation artifacts (exposes + shared + chunks). It does not serve them — dev serving is external (the host's dev server or any static file server). Inwatchmode it rebuilds artifacts to disk on change. The remote runs inside a host shell that owns polyfills, the index document, and bootstrapping.Source:
packages/angular/src/builders/remote/What it already does (via the NF esbuild adapter)
buildForFederationdrives the NF esbuild adapter (createAngularEsbuildContext), which already covers:sourceMap)fileReplacementsdev)assets), incl. watch-mode incremental copystylePreprocessorOptions,inlineStyleLanguage,optimization,preserveSymlinkspassthroughParity gaps
Everything Angular's
@angular/build:applicationdoes in theexecute-build/execute-post-bundle/setup-bundlinglayer is currently absent. Grouped by priority.A. Output-correctness gaps that matter for a remote
$localize(build-slim: i18n / $localize support #67) — the linker plugin never runs andinlineI18nis never called, so$localizemarkers survive raw in output. Nolocalize,i18nMissingTranslation,i18nDuplicateTranslation.define— custom global constant replacement (adapter currently hardcodes onlyngDevMode/ngJitMode).loader— per-extension esbuild loaders; the adapter readsbuilderOptions.loaderbut the builder never sets it.outputHashing— no configurable cache-busting mode.conditions/allowedCommonJsDependencies— custom resolution conditions and CommonJS allow-list warnings not forwarded.B. Post-bundle steps never executed
3rdpartylicenses.txt) — compliance gap.checkBudgets) — no bundle-size enforcement.subresourceIntegrity).logBuildStats+ estimated transfer sizes) — no per-file size table.C. Host-owned / by-design omissions
These are legitimately the host's responsibility for a remote — tracked so the decision is explicit, not silent.
index.html— host-owned by design. The remote builder writes/copies noindex.html(removal done:index-html.tsdeleted,indexschema option removed); output is strictly the federation artifacts (remoteEntry.json+ referenced files) plus copied assets. Angular's index generation (script/style tag injection, preload/modulepreload/preconnect hints, CSP,baseHref/deployUrlrewriting) is also out of scope — the host owns the document and bootstraps the remote.zone.js,@angular/localize/init) must load once in the host as singletons; bundling them in a remote would double-loadzone.jsand contradicts the runtime-$localizeloading model in build-slim: i18n / $localize support #67. A remote that needs a remote-specific polyfill canimportit directly in an exposed entry (it runs on module load), so nopolyfillsbuilder option is planned.styles[]) — host owns global styling; only inline component styles are bundled. Nostylesoption.scripts[]) — host owns global scripts. Noscriptsoption.ngsw.json).outputMode/server— irrelevant to a CSR remote.webWorkerTsConfig— web-worker bundling.security.allowedHosts/autoCsp.watchmode it rebuilds to disk on change); serving in dev is external — the host's dev server or any static file server pointed at the output dir. Removed the Vite server (vite-server.ts), the static middleware (static-middleware.ts), and the SSE build-notifier wiring; dropped theportandbuildNotificationsoptions. (vitestays a package dependency — still used by the fullbuildbuilder's plugin path.) Consequently HMR / live-reload,ssl/proxy/host/allowedHostsdev-server options, and CORS handling are out of scope — they belong to whatever serves the remote.linkedSharedDirsfed as the 3rd arg tosyncNfFileWatcher), so a save inside a linked shared lib does re-bundle fresh federation artifacts to disk inwatchmode. But with no dev server / SSE notifier here, the browser is never told to reload — a linked shared-lib change served through a remote still needs a manual refresh. This is consistent with the design above (reload belongs to whatever serves the remote); it's called out so the gap is explicit rather than surprising. See the follow-up below.Priorities
Highest-value items for remotes specifically: i18n (A),
define/loaderpassthrough (A), and license extraction (B). Category C is host-owned and stays out of the remote builder by design.Sub-tasks / follow-ups
build-slim: i18n / $localize support #67 — i18n /
$localizesupport: runtime$localizewith the host providing translations, plus a self-describingi18n-manifest.jsonnext toremoteEntry.json(option 2). Full design notes & task checklist there.npm link + shared libraries stale federation rebuilds and no browser reload in local dev (NF v4 / Angular 21) #55 — npm-link'd shared libraries in dev: PR fix: Added support for npm link #93 wired
linkedSharedDirsinto both builders' watchers so edits to a locally-linked shared package re-bundle the affected external. Landed for the remote builder:node_modules(3-argsyncNfFileWatcher).rebuildForFederationwith realpath'dchangedFiles).Deferred for the remote builder (a linked-lib edit re-bundles to disk but the browser is not reloaded):
build(shell) builder broadcasts an SSE completion event; the remote has no dev server / notifier (Category C), so remote-served linked-lib edits need a manual refresh. A fix would require the remote to signal whatever serves it — e.g. a cross-process reload hook / ping to the host dev server, or a per-remote reload endpoint — rather than reintroducing an in-process SSE server.