可以在瀏覽器頁面執行 node 程式碼了!webContainer 釋出 1.0
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 方法接受三個引數:
- 字串,為命令名稱,例如
npm
- 陣列:命令的選項
- 非必須,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 的修仙祕籍(點選可跳轉)