Cloudflare Workers 部署 50MB WASM 的踩坑記錄

Cloudflare Workers 有一個隱藏的限制：**單個靜態資源文件不能超過 25MB**。

我的八字演算 WASM 文件有 50MB。

這是一個需要解決的問題。

## 問題分析

WASM 文件大的原因很簡單：八字演算需要內置大量的曆法數據（節氣精確時刻、真太陽時修正係數等），這些數據被直接編譯進了二進制文件。

解決方案有三種：

1. **拆分數據**：將曆法數據從 WASM 中剝離，作爲獨立的 JSON 文件按需加載。
2. **壓縮傳輸**：保持 WASM 不變，使用 Brotli 或 Gzip 壓縮後傳輸，瀏覽器自動解壓。
3. **換平臺**：使用支持更大文件的存儲服務（如 R2）託管 WASM。

方案一改動最大，需要修改 Rust 源碼。方案三引入了額外的複雜度。我選擇了方案二。

## Brotli 壓縮的效果

```bash
# 原始大小
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 文件：

```javascript
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 秒（取決於網絡速度）。

> 有時候，最優雅的解決方案不是重構，而是在正確的地方加一個正確的響應頭。

---

相關工具已部署上線，可以在上方的「八字命盤」入口體驗完整演算功能。