webcontainer とは
stackblitz が提唱して実装している node.js が動くブラウザ環境。container といってるが、 Docker 等とは関係ない。
このコンテナはブラウザ内で node.js (らしきもの)が動くことがターゲットで、現在デモとして next.js をビルドしてプレビューできている。これによって node.js + webpack + next.js cli が動いていることがわかる。
デモはここで試せる。
まだ OSS ではないので、この記事の大部分は想像によって書かれている。
webcontainer 概要
(自分の理解なので話半分に)
ブラウザサンドボックスでも electron なしでも動かせるようになってきた。しかし現在 node.js を動かすには色々と欠けている部分があるので、それらを総称して webcontainer という枠でまとめつつ実装している。
- 仮想ファイルシステム
- 仮想ネットワーク
- マルチスレッドサポート
- プロセス間通信
- POSIX 風のシェルとカーネル
自分も vscode-web をビルドしてみたのでわかるが、vscode web で web と同じ開発体験を得ようとすると、shell がないということに気づく。なのでその周辺をやっている、ということ感じだろう。
github codespace との違いは、ブラウザ自体に node が動く環境を実装しているので、裏で docker イメージを起動したりする必要がなく、ホスト環境のマシンパワーで動くという点だろう。リモートコンテナとの通信ではないので、応答性が高い。
特にフロントエンドは node と ブラウザを行き来する割に同じようなものが動いていたので、これが一本化されるとパフォーマンス的に嬉しい。
webcontainer の新規性
stackblitz を開いてみて、詳しくない人は驚くだろうが、 UI 部分に特に新規性があるわけではない。vscode もすでに web 上で動くビルドが公式にある。というか今までの stackblitz と違ってまんま vscode-web になってしまっている。
terminal も xtermjs/xterm.js: A terminal for the web を使っている。仮想 FS は https://github.com/jvilk/BrowserFS や https://github.com/streamich/memfs 等の実装があって、自分もこれをつなぎ合わせて indexeddb で永続化してみたことがある。vscode の web build を netlify にデプロイする + ファイルシステムを永続化する - mizchi's blog。
node + WASI Backend とのことだが、これも wasmer-js の先行事例がある。これは中で memfs を使っている wasmerio/wasmer-js: Monorepo for Javascript WebAssembly packages by Wasmer
じゃあ何が新しいのか。webcontainer の新規性は、 next.js のために webpack を動かそうとして、 node.js の fs の解決を WASI API で繋いで、それと対話するための js シェルを実装したことだろう。どうやら jsh というらしい。
❯ git init
jsh: command not found: git
(git がない図)
ここから先は予想だが、おそらく jsh の下に POSIX 風の簡易なカーネルがある。カーネルと言うには大げさだが、おそらく web worker でプロセスを立ち上げて、そのプロセス(らしきもの)を管理している。で、それらは(たぶん) wasi インターフェースになっていて、virtual file system を読み書きしている。
仮想ネットワークというのがなにか不明だが、おそらく localhost への bind をリバースプロキシする部分だと思われる。これで http を喋れるようになっている。これを何かしらの方法(service worker?)でリバースプロキシする。
図にするとこんな感じ。赤いところが webcontainer で、自分が新規性があると感じた部分。
実装が公開されていないので想像だが、webcontainer の実装は、 WASM で実装されたカーネル, シェル、 node.js から V8 を抜いて wasi インターフェースを喋るようにした部分、 wasi インターフェースから 仮想 FS に書き込む部分、そのシェルと対話する vscode の debugger の binding 部分 などに分けられると思われる。
jsh が実装している範囲
/bin
を覗くとサポート範囲がわかる。
❯ ls /bin/
cat* env* jsh* mkdir* npm* rm* yarn*
chmod* hostname* ls* mv* npx* turbo*
turbo はこれだろう。
node の REPL も動く。
パーミッションもある。
/projects/next-starter
❯ ls -al
Total: 10
drwxr-xr-x 1 1 staff 8 5 24 16:19 .
drwxr-xr-x 1 1 staff 1 5 24 16:19 ..
-rw-r--r-- 1 1 staff 59 5 24 16:19 .blitzrc.json
drwxrwxrwx 1 1 staff 5 5 24 16:19 .next
-rw-r--r-- 1 1 staff 1581 5 24 16:19 README.md
drwxrwxrwx 1 1 staff 234 5 24 16:19 node_modules
-rw-r--r-- 1 1 staff 198960 5 24 16:19 package-lock.json
-rw-r--r-- 1 1 staff 258 5 24 16:19 package.json
drwxr-xr-x 1 1 staff 3 5 24 16:19 pages
drwxr-xr-x 1 1 staff 2 5 24 16:19 styles
パイプは実装されていなかった
/projects/next-starter
❯ echo 1 > foo
1
/projects/next-starter
❯ chmod +x foo
chmod: ENOENT: no such file or directory, lstat '/projects/next-starter/foo'
触ってみたら分かるが、 シェル入力中に auto completion が動いている
パフォーマンス
webcontainer 自体が数十 MB あるが、+ServiceWorker でキャッシュされているので、開発者のマシンなら問題ない範囲。
(触ってみた感じ vscode-web が 4MB 程度でビルドされていて、 ちょっと前の vscode は独自の loader で起動しないと動かない+RTT が多すぎてローカル以外でパフォーマンスが超絶悪かったが、それは解決したのかな?)
これで何ができるようになるか
結論から言うと、もしこれが成熟してエコシステムが生まれれば、教育現場で普及してきた Chromebook 等で、ゼロインストールで node.js + フロントエンド環境が整うようになる。これが一番大きい。
自分は git がないのが問題に感じる。が、一応 git の wasm ビルドは存在しているが、無理やりビルドしているのでサイズが大きい。ここさえ解決すれば、開発環境として自分は不満がない。一応生の git がローカルになくても、 github rest api で直接 FS 上のものを push することはできるので、代替としてそれでもよい。
エコシステムの話だと、Rust や C++ で wasm + wasi で書かれたものが webcontainer を通して動くようになる。node.js と npm のエコシステムが、ブラウザ上で動くようになる。これ自体は wasmer と似たゴールだが、 node が動くレベルのカーネルを作ろうとしているのと、 vscode とのアダプタ部分に注力している。この周辺でエコシステムが成立すると、 node.js + フロントエンドにまつわるものが、全部 web 上で完結するようになるはず。
とはいえ、ブラウザサンドボックスの制約は受けるし、ITP 等で ストレージがすぐ消される ios safari では PWA は使いづらい。そして自分の観測する限り、 stackblitz は今までほとんどソースコードを公開していない。これは gitpod 等の競合が多すぎるので、ソースコードをパクられないようにということだろうが、もうちょっとオープンにしてほしい。
正直 Deno のほうが webcontainer に向いたアーキテクチャなので、libdeno の wasi ビルドとかのが載せやすそうな気がする。
Discussion
記事でシェルについても言及されているので jsh について調べたことを補足いたします。現時点ではパイプだけでなく
for
,if
や変数の参照といった基本的な機能も使えないためシェルスクリプトを実行するような目的には使えませんでした。ただし文法自体は解釈できているようです。将来的には bash などの複雑なスクリプトにも対応する予定であるという発言を Twitter で見かけたので徐々に実装されていくのだと思われます。ただし私も jsh のソースコードが公開されない可能性が高いと感じており、その根拠は
/bin/jsh
の冒頭に書いてある特許出願中(Portions of this software are patent pending in USA and EU jurisdictions)というコメントです。