可以在瀏覽器頁面執行 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 的修仙祕籍(點選可跳轉)