Skip to content

experimental: remote builder (formerly build-slim) #37

Description

@Aukevanoost

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)
  • Code splitting / chunking
  • Asset copying (assets), incl. watch-mode incremental copy
  • stylePreprocessorOptions, inlineStyleLanguage, optimization, preserveSymlinks passthrough

Parity gaps

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.

B. Post-bundle steps never executed

  • License extraction (3rdpartylicenses.txt) — compliance gap.
  • 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 no index.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 #67i18n / $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.

  • npm link + shared libraries stale federation rebuilds and no browser reload in local dev (NF v4 / Angular 21) #55npm-link'd shared libraries in dev: PR fix: Added support for npm link #93 wired linkedSharedDirs into both builders' watchers so edits to a locally-linked shared package re-bundle the affected external. Landed for the remote builder:

    • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions