Cloudflare Workers に 50MB の WASM をデプロイした時のハマりどころメモ
50MB の八字演算 WASM を Cloudflare Workers にデプロイした全プロセスと、Brotli 圧縮によるファイルサイズ制限の解決方法の記録。
Cloudflare Workers には隠れた制限があります:単一の静的リソースファイルは 25MB を超えられません。
私の八字演算 WASM ファイルは 50MB もあります。
これは解決すべき問題です。
問題の分析
WASM ファイルが大きい理由は簡単です:八字演算には大量の暦データ(節気の正確な時刻、真太陽時補正係数など)を内蔵する必要があり、これらのデータがバイナリファイルに直接コンパイルされているからです。
解決策は3つあります:
- データの分割:暦データを WASM から分離し、独立した JSON ファイルとして必要に応じて読み込む。
- 圧縮転送:WASM はそのままに、Brotli または Gzip で圧縮して転送し、ブラウザが自動的に解凍する。
- プラットフォームの変更:より大きなファイルに対応したストレージサービス(R2 など)で WASM をホスティングする。
案1は変更量が最も大きく、Rust のソースコードを修正する必要があります。案3は追加の複雑さを招きます。私は案2を選びました。
Brotli 圧縮の効果
# 原始大小
ls -lh ganzhi.wasm
# -rwxr-xr-x 50M ganzhi.wasm
# Brotli 壓縮
brotli -q 11 ganzhi.wasm -o ganzhi.wasm.br
ls -lh ganzhi.wasm.br
# -rwxr-xr-x 12M ganzhi.wasm.br
圧縮率は 76% に達し、12MB は Cloudflare の 25MB 制限内に完全に収まります。
Worker の設定
重要なのは、Worker が .wasm.br ファイルに正しいレスポンスヘッダーを設定し、これが Brotli 圧縮された WASM ファイルであることをブラウザに伝えることです:
if (pathname.endsWith('.wasm.br')) {
const response = await env.ASSETS.fetch(request);
const headers = new Headers(response.headers);
headers.set('Content-Type', 'application/wasm');
headers.set('Content-Encoding', 'br');
headers.set('Cache-Control', 'public, max-age=86400');
return new Response(response.body, { status: response.status, headers });
}
ブラウザは Content-Encoding: br を受け取ると自動的に解凍し、その結果を WASM として WebAssembly.instantiate() に渡します。このプロセス全体はフロントエンドコードに対して完全に透過的です。
結果
最終的にデプロイは成功し、八字演算ツールは正常に動作しています。ユーザーがダウンロードするのは 12MB の圧縮ファイルで、ブラウザが解凍すると 50MB の WASM が得られます。このプロセスには約5〜15秒かかります(ネットワーク速度によります)。
時には、最もエレガントな解決策はリファクタリングではなく、正しい場所に正しいレスポンスヘッダーを追加することです。
関連ツールはすでにデプロイ済みで、上部の「八字命盤」エントリーから完全な演算機能を試すことができます。