Architecture: How to implement live in-browser preview of generated Angula...
Documentation for Sessions
🏗️ Architecture: How to implement live in-browser preview of generated Angula...
Date: 2026-03-11
Time: 23:36:35 UTC
Session: gspace1-205.2
Agent: angular
Confidence: 88%
Status: ✅ Documented
📋 Decision Context
Question:
How to implement live in-browser preview of generated Angular platforms without WebContainers (commercial license) or cloud compilation servers?
Task: Not specified
🎯 Decision Made
Chosen:
@rspack/browser (v1.7.2) — Rust bundler compiled to WASM, running entirely in the browser with builtinMemFs for in-memory filesystem, BrowserHttpImportEsmPlugin resolving @angular/* from esm.sh CDN, and a dedicated Service Worker serving compiled output at /_preview/{sessionId}/*
Options Considered:
- WebContainers (@webcontainer/api) — StackBlitz's solution, full Node.js in browser, but commercial license required for production
- @rspack/browser — Rust WASM bundler, MIT license, experimental but fast, in-memory FS
- Cloud compilation server — backend runs ng build and streams result back, adds latency and server cost
- Sandpack (CodeSandbox) — browser bundler but limited Angular support, no SCSS
- Dev server iframe — just ng serve the generated code and iframe it, simple but requires server process
💭 Reasoning
WebContainers requires a commercial license for production use. Cloud compilation adds latency and infrastructure cost. Sandpack has poor Angular 20 support. @rspack/browser is MIT-licensed, compiles Rust to WASM for near-native speed, has builtinMemFs for zero-IO compilation, and BrowserHttpImportEsmPlugin for CDN-based dependency resolution. The Service Worker approach (separate scope at /_preview/) serves compiled assets with proper Content-Type headers, enabling proper module resolution and routing — unlike srcdoc which breaks relative imports. Fallback to WebContainers is trivial since both use a BundlerProvider abstraction. CRITICAL DISCOVERY: @rspack/browser uses top-level await in its WASI loader, which esbuild (used by Angular dev server) rejects. Solution: dynamic import via variable (const modulePath = '@rspack/browser'; await import(modulePath)) prevents esbuild from statically resolving it. Also, the library needs explicit RspackMemFs interface typing since builtinMemFs is synchronous but wrapped in an async import.
📁 Files Involved
libs/libs-structural/platform-preview/src/lib/services/bundler.service.tslibs/libs-structural/platform-preview/src/lib/services/bundler-filesystem.service.tslibs/libs-structural/platform-preview/src/lib/services/preview-server.service.tslibs/libs-structural/platform-preview/src/lib/workers/preview-sw.tslibs/libs-structural/platform-preview/src/lib/config/rspack-angular.config.tslibs/libs-structural/platform-preview/src/lib/config/esm-cdn-map.ts
🔗 Related
- Decision ID:
dev_1773272195174_eakw20q - Session: 205
- Workspace: gspace1
Auto-generated by MCP Smart Consolidation