> 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/2026-nian/w03-gao-jie-wen-ti-pai-cha-xin-de-ti-hui.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项目的整体重构，为团队梳理了很好的可维护性标杆。
