Skip to content

SWC browser WASM transpiler#1790

Open
merryman wants to merge 2 commits intomainfrom
feature/swc-browser-wasm
Open

SWC browser WASM transpiler#1790
merryman wants to merge 2 commits intomainfrom
feature/swc-browser-wasm

Conversation

@merryman
Copy link
Member

Summary

  • Replace Babel with SWC WASM for in-browser module transpilation on fastLoad=false world loads
  • Compiles the existing Rust SWC transforms into a standalone browser WASM module (~5MB), loaded lazily at startup
  • 176 modules transpiled via SWC, 0 Babel fallbacks, 0 runtime errors
  • Automatic fallback to Babel if WASM loading fails — fully backwards-compatible

Performance

Metric SWC Babel Improvement
Total page load 34s 46s 1.3x faster
Transpile time (176 modules) 3.1s ~15s+ ~5x faster
Babel fallbacks 0 N/A

Architecture

Cargo workspace (3 crates sharing transform code):

  • lively-swc-transforms/ — shared library (7 AST visitors, ~4000 lines)
  • lively-swc-plugin/ — existing server-side SWC plugin (wasm32-wasip1)
  • lively-swc-browser/ — new browser WASM entry point (wasm32-unknown-unknown)

JS integration (lively.source-transform/swc/):

  • browser-transform.js — WASM loader + transform wrapper
  • transpiler-setup.js — SystemJS transpiler registration, config mapping, Babel fallback

Key post-processing passes (Phase 3 in lib.rs):

  • fix_async_execute — strips spurious async from execute()
  • hoist_recorder_init — moves recorder init from execute() to factory body
  • rewrite_setters — adds defVar wrapper + default params to SystemJS setters
  • fix_nested_fn_export_calls — strips _export() inside nested functions where the export name is shadowed by a local let/const (SWC system_js scoping bug workaround)
  • strip/restore_export_aliasesexport { Y as a }__export_a__ desugaring to prevent system_js hoisting

Test plan

  • cargo build --target wasm32-unknown-unknown -p lively-swc-browser compiles
  • cargo build --target wasm32-wasip1 -p lively-swc-plugin still works
  • World loads at http://localhost:9011/projects/load?name=__newProject__&fastLoad=false with 0 errors
  • All 176 modules transpiled by SWC (0 Babel fallbacks)
  • ?babelOnly flag falls back to Babel correctly
  • Loading screen build succeeds
  • Compared SWC output against Babel gold standard for structural parity

🤖 Generated with Claude Code

@merryman merryman force-pushed the feature/swc-browser-wasm branch 2 times, most recently from 7d45153 to 3cb114a Compare March 26, 2026 15:44
…world loads

Compile the existing Rust SWC transforms into a standalone browser WASM module
that replaces Babel for in-browser module transpilation. Falls back to Babel
automatically if WASM loading fails.

Cargo workspace with 3 crates sharing transform code:
- lively-swc-transforms: shared library (7 AST visitors)
- lively-swc-plugin: existing server-side plugin (wasm32-wasip1)
- lively-swc-browser: new browser WASM entry (wasm32-unknown-unknown)

JS integration layer (lively.source-transform/swc/):
- browser-transform.js: WASM loader + transform wrapper
- transpiler-setup.js: SystemJS registration, config mapping, Babel fallback

Key post-processing passes for Babel-compatible System.register output:
- Hoist recorder init, rewrite setters with defVar/default params
- Fix system_js bugs: async execute, shadowed export calls, nested fn
  export leaking (let/const shadowing exported names)
- Export alias desugaring (__export_X__ prefix) to prevent system_js hoisting

Performance (176 modules, 0 Babel fallbacks, 0 errors):
- SWC: 34s total load, 3.1s transpile
- Babel: 46s total load
- ~1.3x faster overall, ~5x faster transpilation
@merryman merryman force-pushed the feature/swc-browser-wasm branch from 3cb114a to 4cb17d3 Compare March 26, 2026 15:45
@merryman merryman changed the title SWC browser WASM transpiler — 1.3x faster world load, 0 errors SWC browser WASM transpiler Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant