fix(unity): serve WebGL build from versioned directories - #85
Merged
Conversation
新版推上 Vercel 後,玩家常卡在 90%,必須清快取才能進遊戲,
console 噴 `Not implemented: Class::FromIl2CppType` 與
`RangeError: Maximum call stack size exceeded`。
原因是四個產物(loader / data / framework / wasm)檔名固定,
搭配 `Cache-Control: public, max-age=86400` 變成四個各自過期的
快取項目。瀏覽器可能湊出「新 loader + 舊 wasm」的組合,版本
錯配在 wasm 實例化時就炸開 —— 90% 正是那個位置。
改成每次 build 一個 `/Build/<buildId>/` 目錄,四個檔案同進同出,
不可能混搭:
- scripts/deploy-unity-build.mjs:搬檔、正規化副檔名、寫
version.json、保留最近 3 版(`pnpm deploy:unity <dir>`)
- useUnityBuildVersion:以 `cache: "no-store"` 讀 version.json
- battle.tsx 拆成 BattlePage(閘門)+ UnityGame。useUnityContext
用 useRef 在首次 render 就把 URL 定住,mount 後再改無效,
因此拿到 buildId 才掛載,並用 key={buildId} 強制重建
- 一併補上 companyName / productName / productVersion:Unity 內建的
IndexedDB 快取以這三者為命名空間,並清掉 version 不符的項目。
過去沒帶,所有版本共用預設 "1.0",舊的 43MB data 永不淘汰
- 快取標頭:版本目錄 immutable 一年、version.json no-store
(vercel.json 與 next.config.js 兩邊同步)
- .gitignore 擋掉舊的無版本檔名,避免手滑複製回來
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
新版推上 Vercel 後玩家卡在 90%,必須清快取 / cookie 才能進遊戲:
四個產物(
loader/data/framework/wasm)檔名固定,搭配Cache-Control: public, max-age=86400,變成四個各自過期的快取項目。瀏覽器可能湊出「新 loader + 舊 wasm」的組合,版本錯配在 wasm 實例化時炸開 —— 90% 正是那個位置。清快取之所以有效,就是因為強制重新抓到一致的四個檔案。Fix
改成每次 build 一個
/Build/<buildId>/目錄,四個檔案同進同出,不可能混搭。scripts/deploy-unity-build.mjs— 搬檔進版本目錄、正規化副檔名、寫version.json、保留最近 3 版(pnpm deploy:unity <unity-build-output-dir>)。buildId =<YYYYMMDD>-<HHMM>-<git short sha>useUnityBuildVersion— 以cache: "no-store"讀version.jsonbattle.tsx拆成BattlePage(閘門)+UnityGameimmutable一年、version.jsonno-store(vercel.json與next.config.js兩邊同步).gitignore擋掉舊的無版本檔名,避免手滑複製回來為什麼要拆元件,不能只改 URL 字串
useUnityContext是用useRef在首次 render 就把四個 URL 定住的,mount 之後再改 URL 完全無效(靜默失效,不會報錯)。所以必須等 buildId 到手才掛載UnityGame,並用key={buildId}強制重建整棵子樹。順帶修掉的第二個快取層
webGLDataCaching目前是開的,loader 會把 43MB 的data存進 IndexedDB。它以companyName + productName + productVersion為命名空間,cleanUpCache()只淘汰version不符的項目 —— 而原本battle.tsx這三個欄位一個都沒帶,所有版本共用預設"1.0",舊 data 永遠不會被淘汰。光做 URL 版本化解不掉這層,因此一併補上
productVersion: buildId。快取契約
Cache-Control/Build/<buildId>/*public, max-age=31536000, immutable/Build/version.jsonno-store, must-revalidate/Build/*.unitywebContent-Encoding: brversion.json必須維持不快取 —— 它就是用來查「現在最新是哪一版」的查詢點。版本目錄下的內容不會再變(改內容 = 換 buildId = 換 URL),所以可以放心immutable存一年:回訪玩家零下載,比原本的 24 小時更快,且不可能拿到錯配組合。Content-Type: application/wasm,framework 檔名也不要留.js—— 兩種型別都在 Vercel CDN 的自動壓縮 MIME 清單內,會在已經是 Brotli 的內容上再壓一層而破壞解碼。中性的.unityweb副檔名就是為了避開這件事(由 deploy 腳本自動處理)。發版流程
Testing
pnpm tsc --noEmit乾淨pnpm next lint改動檔案無新問題pnpm build通過pathToRegexp逐條比對四個實際路徑,immutable/no-store/br都落在正確的檔案上(.unityweb規則在版本目錄下仍然命中,Brotli 沒斷)Reviewer 請注意
本 PR 已驗證設定層與線上 header/快取行為,但尚未走過一次完整發版(舊版進快取 → 推新版 → 不清快取重整)。那才是「玩家不用再清快取」的最終證明,建議 merge 後首次發版時確認。
Diff 大小說明
public/Build/底下的產物是從固定路徑搬進版本目錄,git 判定為 pure rename,沒有新增重複 blob。🤖 Generated with Claude Code