CLOUDFLARE WORKERS

Cloudflare の Kitesurf を、公開情報だけで作ってみた

Chromium を使わず、Rust で書いたブラウザエンジンを Wasm にして Workers の isolate で動かす。Cloudflare が 2026 年 8 月に発表した Kitesurf と同じ構成を、発表記事に名前が挙がっている部品だけで組んだものです。ソースコードは非公開なので、中身は見ていません。

以下の画像は全部、この Worker が Wasm の中で描きました。

3 つのブラウザで同じページを撮る

左が本物のブラウザ (Chromium)、中央が Cloudflare の 本物の Kitesurf、右がこの記事で組んだ疑似 Kitesurfです。3 枚は同じ時刻に撮っています — ja.wikipedia のトップページは日ごとに変わるので、別々に撮るとエンジンの違いとページの違いが混ざります。画像を押すと元の大きさで開きます。

撮影 2026-09-08 13:39 UTC。3 枚は並列に撮っているので、同じ時刻・同じ回線です。数字は撮影を頼んでから絵が返るまでの時間で、CPU 時間ではありません。下の「自分で試す」だけはその場で描きます。

ja.wikipedia.org

日本語の見出しと本文、2 カラム、写真 24 枚。CSS は 3 枚で 231 KB
https://ja.wikipedia.org/wiki/メインページ · 1000×780

Chromium202 KB
ja.wikipedia.org を Chromium が描いた画像
2437 ms
Kitesurf390 KB
ja.wikipedia.org を Kitesurf が描いた画像
9021 ms
疑似 Kitesurf366 KB
ja.wikipedia.org を 疑似 Kitesurf が描いた画像
5434 ms

developer.mozilla.org

CSS 20 枚。本文中の map() が等幅で出ている。JS は 938 KB 実行してエラー 0 件
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map · 1000×780

Chromium60 KB
developer.mozilla.org を Chromium が描いた画像
1069 ms
Kitesurf68 KB
developer.mozilla.org を Kitesurf が描いた画像
9840 ms
疑似 Kitesurf57 KB
developer.mozilla.org を 疑似 Kitesurf が描いた画像
4144 ms

react.dev

SSG。ページの JS を実行して、React のハイドレーションが通った状態
https://react.dev/ · 1000×780

Chromium153 KB
react.dev を Chromium が描いた画像
1707 ms
Kitesurf84 KB
react.dev を Kitesurf が描いた画像
3985 ms
疑似 Kitesurf74 KB
react.dev を 疑似 Kitesurf が描いた画像
8780 ms

todomvc.com (React の SPA)

HTML の中は空。見えているものは全部、ページの JS が描いたもの
https://todomvc.com/examples/react/dist/ · 1000×780

Chromium22 KB
todomvc.com (React の SPA) を Chromium が描いた画像
1627 ms
Kitesurf91 KB
todomvc.com (React の SPA) を Kitesurf が描いた画像
2704 ms
疑似 Kitesurf20 KB
todomvc.com (React の SPA) を 疑似 Kitesurf が描いた画像
2830 ms

自分で試す

好きな URL を入れてください。この場に画像が出ます。

外部 CSS と画像は Worker が取ってきてエンジンに渡します。重いページは 10 秒ほどかかります。10 秒で 4 枚までにしています。

JavaScript も動く

ページの <script> を Boa (Rust で書かれた JavaScript エンジン) で実行しています。Workers は eval と new Function を禁じていますが、Boa が自分でコンパイルするので、ページの中の eval は通ります。

同じページを左右に並べます。左はあなたのブラウザが表示したもの、右はこの Worker が Wasm の中で描いた画像です。緑の枠はどちらもページの <script> が書き換えたものです。

あなたのブラウザiframe · 760×560
6 つとも緑になります — 最後の枠の 5000 万回のループも、数十ミリ秒で終わるので
疑似 Kitesurf が描いた画像PNG · 760×560
同じページを、この Worker が描いた画像。上の 5 つの枠は緑で、最後の枠だけ灰色のまま。
最後の枠だけ灰色のまま — Boa はループ 50 万回で JavaScript を止めます。止まる前に書いた 5 つは残ります

違いは最後の枠だけです。ページを単体で開くこともできます。

V8 と Boa が同じ isolate に同居する形になります。Worker のコードは V8 で動き、ページのコードは Wasm の中の Boa で動く。Cloudflare の Kitesurf も同じ構造です。

中身

役割使っているもの
HTML のパースhtml5ever
DOMblitz-dom
CSSStylo — Firefox の CSS エンジン
レイアウトTaffy
テキスト整形Parley
描画blitz-paint + vello_cpu
JavaScriptBoa (blitz-vibey-script 経由)
PNG 化自前。Workers に画像の API が無いので
フォントStatic Assets に置いて起動時に読む
外向きの取得Worker の fetch() 1 箇所だけ

Rust を wasm32-unknown-unknown にビルドして Worker から呼んでいます。Wasm は 15 MB ほど。

できないこと