2026 年前端避坑對照表:
遠端 Mac 上 Vitest/jsdom 與真實 Safari/WebKit
若 Vitest/jsdom 全綠卻在 Safari 翻車,多半是兼容性契約未定義,而非單純測試品質。本文說明 jsdom 能證明什麼、哪些須交給 WebKit,以及如何把遠端 Mac納入發布閘道;附事件、字體、媒體、儲存 API 對照表與三步驗收。延伸:Playwright Safari 兼容性、真機/模擬器/雲端對照、技術見解列表。
01 差異風險總覽
jsdom 是在 Node 中實作網頁標準的程式庫,並非瀏覽器。Vitest 搭配 jsdom 能在 Linux CI 上快速回歸,但繼承了 jsdom 的盲點:沒有真實排版引擎、沒有 GPU 合成,許多子系統僅簡化或缺漏。Safari 使用 Apple 的 WebKit,搭配 ITP、隱私與自動播放等政策,與 Chromium 家族路徑不同。
請把「單元測試通過」視為必要條件,而非充分條件。jsdom 擅長純邏輯、hook、以及在模擬環境中可預測的 DOM 呼叫;無法保證捲動與 passive 事件語意、影片自動播放、localStorage 分區、次像素級字體排版等。若你的使用者大量在 iOS 預設瀏覽器或企業 macOS 上造訪,就必須明確加上第二層:在 Apple 硬體上面向 WebKit 的驗證。
遠端 Mac彌合硬體缺口:SSH/遠端桌面開 Safari 或跑 Playwright WebKit,錄影與 trace 掛發布工單。連線見幫助中心(免登入可讀)。
02 對照表(關鍵 API/渲染)
下表供設計審查與測試計畫使用。「jsdom/Vitest」指預設 environment: 'jsdom';若改用 happy-dom 等環境,風險分布會再位移,需另開矩陣。
| 面向 | jsdom/Vitest(典型) | Safari/WebKit(遠端 Mac) | 測試含義 |
|---|---|---|---|
| 指標/觸控事件 | 合成事件;無真實命中測試與瀏覽器級 passive 預設 |
原生事件管線,iOS 手勢細節 | 在 Safari 手動驗證拖曳、滾輪、捲動容器上 preventDefault 是否合預期 |
| 焦點/鍵盤 | 程式焦點可用;分頁順序簡化 | focus-visible、Shadow DOM、完整鍵盤取用設定 | 以鍵盤走查表單、對話框等 P0 流程 |
| 排版/CSS | 無真實像素級 cascade | WebKit 次像素、flex/grid、100dvh、backdrop-filter 等 |
首屏/sticky header 等區塊做視覺或手動確認 |
| 字體/文字 | 系統字體度量與 macOS/iOS 不一致 | Core Text 塑形、可變字體、斷行與連字符 | 在真 Safari 檢查截斷、中日韓換行與省略號 |
| 媒體(影音) | 多為 mock;編解碼未實際演練 | HLS、CORS、自動播放政策、低耗電模式等 | 在預發布環境用接近使用者的設定跑一條真實播放路徑 |
| 儲存 API | localStorage 常為記憶體內;配額/驅逐不完整 |
ITP 分區、Private Relay、壓力下儲存回收 | 模擬清除網站資料後,驗證登入狀態與離線快取 |
| 計時/排程 | requestAnimationFrame 近似 |
真實幀節奏、Page Visibility | 動畫相關易抖動測試宜以 WebKit E2E 補強,勿僅 jsdom |
| 網路/fetch | MSW 或 vi.stubGlobal 模擬 |
CORS 預檢、Cookie SameSite、第三方規則 | 對真實 origin 做整合測試或 Playwright 網路層驗證 |
03 本地 vs 真機驗證流程
建議固定發布前三步驗收,避免「只靠 Vitest 就上線」。
- 步驟一(本機或 Linux CI):執行
vitest run並維持覆蓋率門檻。凡涉及排版、媒體的用例以標記或拆檔管理,避免在 jsdom 下產生誤報式失敗。 - 步驟二(遠端 Mac,Safari.app):開啟預發布網址,走 P0 漏斗:登入、付費牆、影音、上傳,以及對照表中相關功能。搭配Web Inspector 遠端聯調 FAQ看主控台與效能;亦可參考Safari/WebKit 除錯實務。
- 步驟三(自動化對齊):在同一台 Mac 以 Playwright
webkit對預發布跑腳本並封存 trace。建置到測試的銜接可對照Vite/Webpack 部署與 Safari 驗證步驟。
Safari 主版本盡量對齊分析基線;冒煙時關閉非必要延伸功能;若產品含串流或直播,需測視窗與全螢幕播放;並至少做一次清除網站資料,模擬 ITP 相關情境後的回訪使用者。
04 CI 參數建議
管線建議拆分:每個 PR 跑輕量 jsdom;在 main 或夜間於遠端 Mac runner 跑 WebKit。
| 議題 | 建議設定 | 理由 |
|---|---|---|
| Vitest workers | --pool=threads,共享 Mac 上 maxWorkers 勿超過 CPU−1 |
避免與 Playwright 搶滿核心導致雙雙不穩定 |
| 逾時 | E2E 放寬 testTimeout;單元維持嚴格 |
WebKit 冷啟動與影片就緒時間波動大 |
| Playwright | 僅在 macOS agent 執行 npx playwright install webkit |
Linux 上的 WebKit 不會等同使用者 Safari;儀表板需標示執行環境 |
| 產物 | 失敗必傳 trace+錄影 | 與E2E 日誌分診與遠端 Mac 流程一類工作銜接 |
測試前 Node 與工具鏈對齊,可一併參考遠端 Mac:Node/npm 與 Safari 兼容性清單與前端避坑:Node、npm 與 Safari 遠端 Mac 對照。
05 FAQ
Vitest 能否取代 Safari 手動檢查?不能。jsdom 驗的是模擬環境下的邏輯與 API 使用方式;Safari 在事件、儲存、媒體與排版上實作不同。請保留三步閘道:單元測試 → Mac 上 WebKit/Safari → 預發布/真機覆蓋 P0。
為何要遠端 Mac?真 Safari 僅在 Apple 平台;遠端節點讓團隊共用與使用者相近的 WebKit 與繪圖堆疊,Linux CI 無法替代。
Playwright webkit 等於 Safari 嗎?在 macOS 上遠比 jsdom 可靠,仍非每一條政策與 GPU 路徑都與 Safari.app 一致。建議自動化+關鍵路徑至少一次真 Safari。
如何平衡速度與覆蓋?推送跑 jsdom;夜間/main 在專用 Mac 跑 WebKit;WebKit 紅燈或未勾選手動 Safari 清單則阻擋上線。
先把功能對照 jsdom/WebKit 矩陣;Vitest 負責速度;發布以遠端 Mac 上的 Safari 與 Playwright WebKit trace 當閘道。明確文件化「僅 jsdom」與「必須 WebKit」的測試分類,團隊才不會把綠燈 CI 誤當「Safari 一定沒問題」。