StackBlitz · @webcontainer/api
A complete OS for the browser — built on WebAssembly. 為瀏覽器打造的完整執行環境,以 WebAssembly 為核心。
press → to continue 按 → 繼續
A browser-native runtime that executes Node.js, npm, and shell commands entirely inside the browser tab. Built by StackBlitz, it powers StackBlitz.com. 一個瀏覽器原生的執行環境,可直接在瀏覽器分頁內執行 Node.js、npm 與 shell 指令,無需任何後端。由 StackBlitz 開發,為 StackBlitz.com 提供技術核心。
Cloud VM sandboxes work, but come with serious trade-offs. Cloud VM 沙盒雖然可行,但帶來了不少代價。
Proven at scale — powering millions of StackBlitz users and the interactive docs of Svelte, Angular, and Nuxt. 已通過大規模驗證——驅動數百萬 StackBlitz 使用者,並支援 Svelte、Angular、Nuxt 的互動式官方文件。
WebContainers stack four modern browser primitives. WebContainers 建立在四項現代瀏覽器底層技術之上。
The Node.js runtime binary (C/C++) can't run in browsers directly — browsers only execute JavaScript and
WASM. So the C/C++ parts are compiled to WASM; Node.js's built-in JS modules still run in the browser's
own V8, avoiding double-VM overhead. OS-level calls like open and fork are
intercepted and re-implemented with browser APIs.Node.js 的 runtime binary 以 C/C++ 撰寫,瀏覽器無法直接執行——瀏覽器只能跑 JavaScript 與 WASM。因此 C/C++
部分編譯為 WASM,Node.js 的 JavaScript 內建模組仍由瀏覽器原生 V8
執行,無雙重虛擬機損耗。open、fork 等 OS 呼叫則被攔截並以瀏覽器 API
重新實作。
SharedArrayBuffer is a block of memory shared across Workers — any Worker can read or write
it directly, with no message-passing overhead. Atomics provides synchronization on top:
Atomics.wait() blocks a Worker until notified, and Atomics.notify() wakes it up.
Together they let WebContainers emulate synchronous blocking calls (e.g. readFileSync) across
Worker boundaries.SharedArrayBuffer 是可跨 Worker 共享的記憶體區塊——任何 Worker
都能直接讀寫,無需訊息傳遞。Atomics 在此之上提供同步機制:Atomics.wait() 讓
Worker 阻塞等待,Atomics.notify() 將其喚醒。兩者合力讓 WebContainers 能在跨 Worker
的環境中模擬 Node.js 同步阻塞呼叫(如 readFileSync)。
The container's HTTP server has no real TCP port — it runs inside a WASM Worker. When a port opens,
WebContainers generates a unique HTTPS proxy URL (e.g. *.webcontainer-api.io) for it. The
Service Worker intercepts fetch requests to that URL, forwards them to the WASM Worker, and
returns the response — so the <iframe> behaves as if it's talking to a real
server.容器內的 HTTP 伺服器沒有真實 TCP 連接埠,跑在 WASM Worker 裡。當 port 開啟時,WebContainers
會為它產生一個專屬的 HTTPS 代理網址(如 *.webcontainer-api.io)。Service Worker
攔截送往該網址的 fetch 請求,轉發給 WASM Worker 並回傳回應——<iframe>
的行為就像在存取一個真實的伺服器。
Browsers run JS on a single main thread — any blocking operation freezes the UI. WebContainers gives each
spawned process its own Web Worker, enabling true parallelism (e.g. running a dev server and
npm install simultaneously). The WASM runtime must also run in a Worker because
Atomics.wait() — required by Layer 2 — is forbidden on the main thread.瀏覽器的 JS 預設只有一條主執行緒,任何阻塞操作都會導致畫面卡住。WebContainers 為每個子 Process 配置獨立的
Web Worker,實現真正的平行執行(例如同時跑 dev server 與 npm install)。WASM runtime
也必須跑在 Worker 裡,因為 Layer 2 依賴的 Atomics.wait() 在主執行緒中是被禁用的。
A minimal in-browser IDE — WebContainers boots a real Node.js runtime and mounts a live Express app, all inside the browser tab. 一個極簡的瀏覽器內 IDE:WebContainers 啟動真實的 Node.js 執行環境,並掛載一個可即時編輯的 Express 應用程式,完全在瀏覽器分頁中運行。
Open Demo ↗ 開啟 Demo ↗Four lifecycle steps — from zero to a running server in the browser. 四個生命週期階段,帶你從零開始在瀏覽器中啟動一台伺服器。
WebContainer.boot()
Initializes the WASM runtime. One call per page load.初始化 WASM 執行環境,每次頁面載入只需呼叫一次。
container.mount(tree)
Write a FileSystemTree snapshot into the virtual FS.將 FileSystemTree 物件快照載入至虛擬檔案系統。
container.spawn('jsh')
Start a shell or Node process. Streams stdin/stdout.啟動 Shell 或 Node Process,以串流方式傳輸 stdin/stdout。
'server-ready'
A proxy URL is emitted when a port opens.伺服器啟動後觸發事件,取得可載入 iframe 的網址。
An in-memory FS inside the WASM runtime — shared between host JS and the Node.js process, never touching the host disk. 存在於 WASM runtime 記憶體內的檔案系統,Host JS 與 Node.js process 共用同一份,完全不存取主機磁碟。
container.fs.*
Host JS · container.fs.*
fs shim
fs.readFile / fs.writeFile
Node.js process · fs.readFile / fs.writeFile
container.mount(tree)
— initialize FS from a FileSystemTree object— 以 FileSystemTree 物件初始化整份 FS
container.fs.readFile(path)
— returns Uint8Array or string— 回傳 Uint8Array 或字串
container.fs.writeFile(path, data)
— write or overwrite a file— 寫入或覆寫指定檔案
container.fs.mkdir(path)
— create directories recursively— 遞迴建立目錄結構
container.fs.rm(path)
— remove files or directories— 刪除檔案或目錄
container.fs.watch(path, cb)
— observe changes (like Node's fs.watch)— 監聽變更(同 Node.js fs.watch)
// 1. Hardcoded (FileSystemTree object) await container.mount({ 'index.js': { file: { contents: src } } }); // 2. From an API (server returns FileSystemTree as JSON) const tree = await fetch('/api/project').then(r => r.json()); await container.mount(tree); // 3. Snapshot (@webcontainer/snapshot — binary, recommended) // server: import { snapshot } from '@webcontainer/snapshot' // res.send(await snapshot('./my-project')) const buf = await fetch('/snapshot').then(r => r.arrayBuffer()); await container.mount(buf); // mount() accepts ArrayBuffer directly
spawn() forks a real process inside the Service Worker sandbox — its I/O is bridged back to the
browser as Web Streams.
spawn() 在 Service Worker 沙盒中 fork 真實 process,I/O 透過 Web Streams 傳回主頁面。
xterm.js
npm · node · jsh
shell.output
— ReadableStream of stdout + stderr— stdout+stderr 的 ReadableStream
shell.input.getWriter()
— WritableStream writer for stdin— stdin 的 WritableStream writer
shell.exit
— Promise resolving with exit code— 解析為離開代碼的 Promise
shell.kill()
— send SIGTERM to terminate— 送出 SIGTERM 終止 process
shell.resize({ cols, rows })
— update terminal dimensions— 更新終端機尺寸
const shell = await container .spawn('jsh', { terminal: { cols, rows } }); // stdout → xterm.js shell.output.pipeTo( new WritableStream({ write(data) { terminal.write(data); } }) ); // xterm.js keystrokes → stdin const input = shell.input.getWriter(); terminal.onData((data) => { input.write(data); });
Servers inside the container are reachable from the host page via a Service Worker proxy. 容器內的伺服器可透過 Service Worker 代理,從外層頁面直接存取。
'server-ready' event fires with a
proxy URLProcess 監聽連接埠後,'server-ready' 事件隨即觸發,並回傳對應的代理網址
<iframe> for a live preview from the same page將網址載入 <iframe>,即可在同一頁面內即時預覽執行結果
container.on('server-ready', (port, url) => { // url is the proxy URL iframe.src = url; } );
<iframe src="*.webcontainer-api.io">
瀏覽器分頁 ·
<iframe src="*.webcontainer-api.io">
After Spectre/Meltdown attacks (2018), browsers disabled SharedArrayBuffer by default as a
side-channel mitigation. Cross-Origin-Opener-Policy (COOP) +
Cross-Origin-Embedder-Policy (COEP) signal that the page is cross-origin isolated — the
browser then re-enables SharedArrayBuffer, which WebContainers depends on for synchronous
Node.js APIs. Without these headers, WebContainer.boot() throws immediately.
2018 年 Spectre/Meltdown 攻擊事件後,瀏覽器預設停用
SharedArrayBuffer 以防範旁路攻擊(side-channel attack)。
設定
Cross-Origin-Opener-Policy(COOP)+
Cross-Origin-Embedder-Policy(COEP)標頭可向瀏覽器宣告頁面已完成跨來源隔離,瀏覽器才會重新啟用 SharedArrayBuffer——這正是
WebContainers 實作 Node.js 同步 API 的基礎。
缺少這兩個標頭,WebContainer.boot() 將直接拋出例外。
Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: cross-origin. CDN assets without this header will fail to load.COEP 會封鎖所有跨來源子資源(圖片、字型、script…),除非該資源回應中包含
Cross-Origin-Resource-Policy: cross-origin。 未加此標頭的 CDN 資源將無法載入。
Any environment that benefits from an isolated, zero-setup Node.js runtime. 凡是需要隔離、免安裝的 Node.js 執行環境,都是 WebContainers 的舞台。
VS Code-like tools with no backend. Each tab is its own isolated runtime.無需後端基礎設施,打造類 VS Code 的開發工具,每個分頁各自擁有完全隔離的執行環境。
Runnable code samples embedded in docs. Readers edit and run without leaving the page.在文件中直接嵌入可執行的程式碼範例,讀者不必離開頁面就能即時編輯與執行。
Isolated environments for coding challenges and interviews with real npm support.為程式競賽、技術面試等場景提供支援真實 npm 的隔離執行環境。
A running app as a URL — no deployment pipeline, no server costs.以一條網址分享正在執行的應用程式,無需部署流程,也不需要任何伺服器費用。
Give LLMs a sandboxed Node.js environment to write, run, and iterate on code safely.為大型語言模型提供沙盒化的 Node.js 執行環境,讓 AI 能安全地撰寫、執行並反覆迭代程式碼。
Run tests and builds client-side. No CI server, no queue — instant feedback.直接在瀏覽器端執行測試與建置,無需 CI 伺服器,也不用排隊等待,立即獲得回饋。