> For the complete documentation index, see [llms.txt](https://weekly-essay.mikey.wang/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://weekly-essay.mikey.wang/zh-hant/2026/w03-lessons-from-advanced-troubleshooting.md).

# W03-高階問題排查心得體會

我們有一個困擾了近 3 年的 Webpack 幽靈問題，上週有了重大進展。藉機想總結一下前端裡古怪艱深問題的特點，以及處理這類難搞問題的心得體會。

***

#### 古怪艱深的問題可以按照代碼有沒有問題切為兩類

* 第一類是代碼有很隱蔽的設計缺陷。 這類問題源於代碼設計上潛伏的邏輯缺陷，往往在特殊條件下才暴露出來。比如代碼對異步、併發或狀態假設不當，在低性能、特定執行順序才會暴露。實際遇到最多的就是時序競態問題，後邊會提到具體例子。
* 第二類往往根因不在代碼本身，需要放在一個充滿不確定性的系統裡尋找真相。 這個恰恰是前端問題排查的高階所在，不光要寫對代碼，還能理解代碼將運行在什麼樣的世界裡。這個世界可以稱之為“不確定的運行時”，其不確定的程度經常會讓觀測和復現都充滿挑戰。

***

#### 不確定的運行時

可以理解為是一種技術假設，假設除了代碼，都是不可靠的。目的是做好防禦工作。

從代碼被 build 開始，就可以算作不確定運行時的起點。

> Build（人為選型） → Container（強定製） → OS & Hardware（高度碎片化）→ User & Physical Context（不可控）。

**1. Build：基建與構建產物差異**

Polyfill、運行時庫、構建配置版本不一致，可能導致新語法在老環境直接報錯，或重複/錯誤注入引發異常。

> 前段時間月付遇到的問題，從 Webpack 切換到 Rspack 構建後，在低端設備上出現了 Promise/thenable 執行順序異常的情況。構建工具本身可能並沒有 bug，而構建產物的 runtime 行為差異會觸發問題。因為 Webpack 有一套複雜的 runtime，用 Promise/thenable 協調模塊加載順序。
>
> 商家收銀臺在快驢端發現過 set cookie 失效的問題，是客戶端內不同線程之間的執行時序導致的。

**2. Container：宿主 App / WebView 內核差異**

不同 WebView 在 JS 執行、CSS 渲染、安全與接口行為上不完全一致，殼層還可能注入或限制 API，導致同一 H5 在不同容器中表現不一致。

> 很典型的像 iOS 的攔截器，容器對網絡請求、路由跳轉等設有攔截機制，錯誤或重複的攔截實現就會造成問題。比如在慧銷遇到過 set cookie 失敗導致 token 失效。在外賣商家端踩過離線化的坑。
>
> 在外賣商家端，曾經還發現過會注入一個hook，如果沒有 knb.js 會自主引入1.9.1版本，導致在安卓偶發訂閱 appear 成功，但是沒有執行回調。

**3. OS & Hardware：OS 與設備碎片化**

不同廠商 ROM、機型、分辨率與系統版本差異，可能帶來特定機型崩潰、佈局異常或性能問題。

> 在外賣商家 iOS 端出現過單用戶大量重複調用 yoda 問題，在第二年解決另一個問題的時候，發現可以併案處理，最終定位是低端機下可用內存不足導致。當內存告警後，由於保活機制的存在，WebView 持續多次調用 reload 方法，進而出現單用戶短時間內頻繁進入頁面。

**4. User & Physical Context：用戶真實運行環境差異**

用戶千差萬別的使用方式和所處環境，比如弱網、低電量、存儲空間不足等，都會形成諸多不可控變量，造成邊緣情況下的異常現象。這些問題由於缺乏可重複性，往往給排查帶來很大挑戰，需要結合埋點日誌和用戶操作記錄才能分析出線索。

> 在三方支付場景遇到過微信雙開導致支付失敗的問題。部分用戶會使用系統或第三方提供的雙開功能，在一部手機上運行同一 App 的兩個實例。這種機制會破壞應用單例假設或 IPC 鏈路，會導致意想不到的問題。

***

#### 我栽過很多坑，談一些心得體會，並分享兩個案例

一、破我執，不是所有的艱深問題都需要立刻“完美解釋”。 如果已經引起事故，第一優先級是釋放周圍對你的壓力。先找一個可控的 workaround 把風險封住，讓大家的關注點快速轉移出去。絕大多數人並不在意那個“終極根因”，先穩住局勢，才有資格慢慢追真相。

二、有恆心，勇於直面挑戰，才能練就技術深度。 很多問題是在長期等待中突然被解決的。當走入死穴後，把問題放在那裡，等機會或者靈感，缺什麼補什麼，但不要放棄。

***

#### 案例一：Webpack 構建產物不穩定問題

開頭提到的 Webpack 構建產物不穩定問題，就是一個用了近三年時間、由淺入深不斷逼近真相的過程。

1. 問題現象 問題現象是 Webpack 構建產物有時會不可用，線上偶發白屏。最初接觸這個問題，發現找不到根因，但由此優化了一個流水線的發包機制問題，保證了線上白名單驗證和全量發佈的是同一個包。
2. 配置分析 後來洪澤專門做了一次 Webpack 配置分析，定位到三方依賴裡 ESM 與 CJS 混用導致構建異常，針對配置做了優化，但依舊會存在異常產物。
3. 社會實驗與折中 去年劍鑽在基本功傳幫帶上，對構建異常做了一場主題分享。帶著大家現場復現了構建產物不穩定的問題，通過這次社會實驗，提升了團隊對構建的認知深度。同時找到了一個更有效的配置開關，如果把異步打包構建關掉，異常產物就不再出現了，代價是構建速度。
4. 最終解決 上週，劍鑽提供了一個新的解決方案。找到了構建物中 n.n() 包裝這個重要特徵，通過檢查構建產物內的 CJS 壓縮特徵是否符合預期，保證線上打包的正確性。可以完全封堵質量風險的漏洞。

至此這個問題我覺得就可以了結了，再有餘力的話，就是能幫 Webpack 徹底解決異步構建 CJS 模塊的問題，提個 PR 過去。

***

#### 案例二：Alpha項目營銷重構

問題可以被解決，但不是所有問題都能得到圓滿的技術解釋。應對問題的過程更重要。

Alpha項目曾經在一次營銷重構中，引起開戶轉化率下滑。持續了兩個多月才解決，暴露了一系列問題。最終也沒有找到技術根因，也沒有條件再去復現了，永遠不可能有圓滿的技術解釋了。

但在這個過程，我們對質量有了深切的認識。那段時間補齊了業務指標的實時觀測能力，AB 實驗的能力，線下質量的常態化運營，以及對回滾策略和決策的深入反思。這個事件也直接促成次年Alpha項目的整體重構，為團隊梳理了很好的可維護性標杆。
