S264 Handoff
Documentation for Sessions
S264: Technical Handoff — Platform Preview Compilation Overhaul
Session: 264.1 Date: 2026-03-24 Branch: session-261-266
Summary
Fixed critical "Failed to load Angular compiler from CDN" error in Live Preview. Root cause: esm.sh CDN singleton isolation — Angular packages bundled separate @angular/core instances, breaking JIT compiler registration. Solution: self-hosted Angular ESM runtime with shared singletons + future-proof AOT compilation architecture.
Architecture Changes
Self-Hosted Angular Runtime (Phase 1 — ACTIVE)
BEFORE: Preview iframe → import("https://esm.sh/@angular/core@20") → CDN re-bundles → duplicate singletons → BROKEN
AFTER: Preview iframe → import("http://localhost:6200/angular-runtime/core.mjs") → shared singleton → WORKS
Build: tools/scripts/build/bundle-angular-runtime.ts
- Uses esbuild with custom
exactExternalPlugin(esbuild'sexternalprefix-matches scoped packages, breaking subpath bundling) - Post-processes output: rewrites bare
@angular/core→./core.mjs(relative imports ensure singleton) - Animation subpaths use noop stubs (FESM flat bundles duplicate
DomRendererFactory2) - Output:
dist/angular-runtime/*.mjs(21 packages, 3.7MB)
Runtime flow:
BundlerService.compile()callsbuildPreviewExternalsMap(window.location.origin)→ absolute URLs- rspack externalizes Angular packages to
http://localhost:6200/angular-runtime/*.mjs PreviewServerService.updateAssets()rewrites remaining bare specifiers to absolute URLs- Prerequisites script loads zone.js + compiler + PBD from
/angular-runtime/before main.js parse - Blob URL iframe resolves all imports to shared
/angular-runtime/modules
Compilation Strategy (Phase 2 — CODE READY, NOT WIRED)
Interface: libs/libs-structural/platform-preview/src/lib/strategies/compilation-strategy.ts
CompilationStrategy {
mode: 'jit' | 'aot'
getMainTsInjection(): MainTsInjection
getPrerequisites(runtimeBase): PrerequisiteModules
getExternals(origin): Record<string, string>
transformSources(files): SourceTransformResult
}
Implementations: JitCompilationStrategy (current) + AotCompilationStrategy (uses Phase 3 compiler)
Lightweight Template Compiler (Phase 3 — CODE READY, NOT WIRED)
Template HTML → TemplateParser → TemplateAST → IvyCodegen → Ivy Instructions
template-parser.ts: Handles elements, bindings, events, @if, @for, @switch, ng-container, ng-contentivy-codegen.ts: Generates CREATE (rf & 1) and UPDATE (rf & 2) blocks with proper node indexingdecorator-transformer.ts: String-level @Component → Ivy static fields transformation
Bugs Fixed
- CDN singleton isolation — Self-hosted Angular runtime (Phase 1)
- NG0201 _DomRendererFactory2 — Removed
provideAnimations()(FESM flat bundle duplicates) - NG0200 Circular dependency for RendererFactory2 — Same root cause as #2
- NG0304 unknown ggs element —
NO_ERRORS_SCHEMAinjected into all @Component decorators - NG0303 unknown property on ggs — Same fix as #4
Wiring TODO (for next session)
To activate Phase 2+3:
- Add
CompilationStrategyas injectable inBundlerService - Call
strategy.getExternals()instead ofbuildPreviewExternalsMap()directly - Call
strategy.transformSources()in the enrichment pipeline - Call
strategy.getPrerequisites()inPreviewServerService - Call
strategy.getMainTsInjection()inBundlerFilesystemService.synthesizeMainTs() - Add toggle in UI or config to switch between JIT/AOT
- Test AOT on real generated modules, verify template compiler handles all patterns
Key Conventions Established
- Angular preview packages MUST be self-hosted, never loaded from CDN
- FESM subpath bundles that share code with parent (e.g., platform-browser/animations) MUST use noop stubs, not full bundles
- All preview @Component decorators MUST have
schemas: [NO_ERRORS_SCHEMA] dist/angular-runtime/is auto-rebuilt via NXdependsOn— no manual step needed for dev- After Angular version upgrades, re-run
bundle-angular-runtime.ts