可以在瀏覽器頁面運行 node 代碼了!webContainer 發佈 1.0

語言: CN / TW / HK

2021年5月12日, stackblitz 團隊在 谷歌 I/O 上提到了一下的內容:

幾年前,我們就能感覺到,web 開發正在走向一個關鍵的拐點。

WebAssembly 和新的 capabilities API 的出現,使得編寫一個基於 WebAssembly 的操作系統似乎成為可能,該操作系統功能強大到可以完全在瀏覽器中運行 Node.js。 它提供一個比本地環境更快、更安全、更一致的卓越開發環境,以實現無縫代碼協作,而無需設置本地環境,這個目標似乎離 Web 開發人員越來越近了。

這項技術在 StackBlitz 中的在線 IDE 中可以體驗到,其性能可以碾壓同類的 web IDE

如今,這項技術終於對公眾開放。

在2021年,我們宣佈了 WebContainer,這是一個完全新穎的基於 WebAssembly 的操作系統,它使Node.js能夠完全在瀏覽器內部運行。在過去的兩年中,數以百萬計的開發人員每月在 Stackblitz 編輯中使用 WebContainers。

今天,我們很高興發佈 WebContainer API供公眾使用,我們邀請整個JavaScript和Node.js社區與我們一起在WebContainers上構建您自己的應用程序!我們構建了Stackblitz經典編輯器,CodeFlow IDE和Web Publisher:我們迫不及待地想看看您的想法!

我們可以直接在 webContainer 官網在線體驗這項技術

WebContainer 是什麼

官方文檔中的定義

WebContainers 是一個基於瀏覽器的運行時用於執行 Node.js 應用程序和操作系統命令,它完全運行在您的瀏覽器頁面中。

我的理解,webContainer 就是一個可以運行在瀏覽器頁面中的微型操作系統,提供了文件系統運行進程的能力,同時內置了 nodejs、npm/yarn/pnpm 等包管理器

主要特性

  • 能夠在瀏覽器中運行 node.js 及其工具鏈(如:webpack、vite 等)
  • 靈活:在 WebContainers 支持下,編碼體驗將會大幅提升
  • 安全:所有內容都運行在瀏覽器頁面中,非常安全
  • 快速:毫秒級啟動整個開發環境
  • 始終開源免費

對於服務提供方(例如在線 IDE)來説,與在雲端虛擬機上運行命令相比,有以下好處:

  • 無與倫比的用户體驗。沒有延遲。比本地主機快。離線工作。
  • 成本效益。計算是在本地完成的。不購買雲服務器。
  • 可以擴大用户規模。以前受限於雲服務器的規模,如今直接運行在客户端,使用客户端的算力
  • 服務器安全,代碼運行在客户側,不擔心服務器運行惡意邏輯,例如挖礦

快速開始

啟動 webContainer

在代碼中,找個地方調用以下代碼即可

```javascript import { WebContainer } from '@webcontainer/api';

// Call only once const webcontainerInstance = await WebContainer.boot(); ```

啟動 webContainer,相當於電腦開機,啟動完才能用

設置跨域隔離

WebContainers 需要使用 SharedArrayBuffer 這個 API(這個 API 有安全需求)。因此,您需要設置Coop/COEP標頭:

```yaml

保護源站免受侵害

Cross-Origin-Embedder-Policy: require-corp

保護源站免受攻擊

Cross-Origin-Opener-Policy: same-origin ```

另外,網站必須要使用 https,本地開發時使用 localhost 也行,否則 SharedArrayBuffer 是不安全的,會被禁用。

掛載文件

使用 mount API 進行掛載文件和目錄

``javascript const files = { // 這是一個文件,package.json 是文件名 'package.json': { file: { contents: { "name": "vite-starter", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "devDependencies": { "vite": "^4.0.4" } }, }, }, // 這是一個目錄,src 是目錄名 src: { // 目錄下會有 directory 的屬性 directory: { // 這是一個文件,叫 mian.js 'main.js': { // 文件下有 file 的屬性 file: { contents: console.log('Hello from WebContainers!') `, }, }, }, }, };

await webcontainerInstance.mount(files); ```

然後就可以通過 readFile 讀取文件:

javascript const file = await webcontainerInstance.fs.readFile('/package.json');

目前 webContainer 的 fs 支持以下幾種文件操作:

運行進程

可以在 webContainer 中運行命令,例如 npm install

javascript webcontainerInstance.spawn('npm', ['install']);

spawn 方法接受三個參數:

  1. 字符串,為命令名稱,例如 npm
  2. 數組:命令的選項
  3. 非必須,spawn 的參數(例如指定環境變量,禁止輸出等)

安裝依賴

下面是一個封裝好的安裝依賴的函數

javascript async function installDependencies() { const installProcess = await webcontainerInstance.spawn('npm', ['install']); return installProcess.exit; }

讀取進程的輸出

調用 Spawn 函數返回 WebContainerProcess。它的 output 屬性是一個可讀流 readableStream <string> ,它接收所有的輸出,包括 stdout and stderr,下面代碼可已經進程的輸出,打印出來

```javascript const installProcess = await webcontainerInstance.spawn('npm', ['install']);

installProcess.output.pipeTo(new WritableStream({ write(data) { console.log(data); } })); ```

運行 dev Server

有些命令可以啟動 dev Server,例如 npm run start 啟動一個 vite/express Server。

這時候,可以用過 on 監聽到 server-ready 事件

``javascript async function startDevServer() { // 執行npm run start` 啟動 Express app await webcontainerInstance.spawn('npm', ['run', 'start']);

// 等待 server-ready 事件 webcontainerInstance.on('server-ready', (port, url) => { // 通過這個 url,就能訪問 server window.open(url) }); } ```

我們平時啟動的 dev Server,會通過類似 http://localhost:8080 的方式進行訪問,但如果在網頁中運行 dev Server就不行了,因為由於安全限制,網頁沒有足夠的權限綁定端口。

因此 webContainer 會提供一個 url,代替 http://localhost:8080 去訪問,這也就是 server-ready 事件,會在回調參數中傳 url 的原因

url 長這樣:https://localhost5173-3ca0-2jv4wvy8--3111.local-corp.webcontainer.io/

這個請求實際上沒有請求到外部,而是在 Service Worker 中直接返回了,通過這樣的方式,達到了與平時訪問 http://localhost:8080 一樣的效果

總結

webContainer 非常適合交互式編碼體驗,它可以用在生產級IDE,編程教程,下一代文檔等應用上。雖然看起來功能十分有限,但這其實是一個很有意義的嘗,是一個從 0 到 1 的突破,嘗試在瀏覽器端運行一個微型的操作系統,相信不久的未來,不僅僅是 nodejs,其他的語言,例如 python、Java,或者運行其他更多的程序。

如果這篇文章對您有所幫助,可以點贊加收藏👍,您的鼓勵是我創作路上的最大的動力。也可以關注我的公眾號訂閲後續的文章:Candy 的修仙祕籍(點擊可跳轉)