页面白屏卡住,通常是 JavaScript 死循环/死递归 (CPU爆满)或 内存暴涨(占满RAM)导致的。别慌,按下面这套"外科手术式"的排查流程走,你不需要瞎改代码:
第一刀:紧急"暂停"(区分是CPU卡死还是内存泄漏)
页面卡住时,千万不要立刻刷新(刷新可能丢失现场)。
-
按
F12打开开发者工具 ,切换到 Sources(源代码) 面板。 -
点击右上角的"暂停"按钮(⏸️) (或按
F8快捷键)。- 如果成功暂停,并高亮显示在某一行代码上 :说明是 JS 死循环/死递归(CPU干烧了)。此时看调用堆栈(Call Stack),那个一直在重复调用的函数就是罪魁祸首。
- 如果按了
F8毫无反应,或页面直接崩溃提示"内存不足" :说明是 内存泄漏(变量无限堆积)。直接看下面的"第三刀"。
第二刀:CPU 卡死(抓取 Performance 火焰图)
如果按暂停能停住,但代码太复杂看不出哪里循环,用性能录制:
-
回到 Performance(性能) 面板,点击左上角的 录制按钮(●) 。
-
录制 3-5 秒,然后强行停止(页面可能会短暂变卡,正常)。
-
查看火焰图(Main 线程):
- 看哪一栏的色块又高又宽 ,颜色通常为黄色(Scripting) 。
- 展开最宽的那个函数堆栈,最底层那个名为
(anonymous)或你熟悉的业务函数,就是死循环所在。
-
定位到具体行号后,重点检查
while、for循环的结束条件 是否写反了(如i >= 0忘给递减),或者requestAnimationFrame里是否在不断无限追加 DOM。
第三刀:内存暴涨(抓取 Heap 快照)
如果按暂停无效且页面崩溃,大概率是内存被吃满。
-
切换到 Memory(内存) 面板。
-
先拍一张 Heap snapshot(堆快照) (如果还能拍的话)。
-
刷新页面,等页面刚加载出来还没卡死的那一瞬间,再拍第二张快照。
-
将两张快照对比(选择 Comparison 视图):
- 按 "New #" (新增对象数量)排序。
- 重点看
Array、String或你自定义的Class名称。如果数量暴增几十万,说明某个push或concat操作在无限追加数据(比如监听滚动事件时,忘清空旧数据,不断往数组里塞节点)。
第四刀:排查"渲染层"卡顿(白屏且无报错)
如果上面都查不出,且页面只是白屏、没有崩溃,可能是 CSS 重绘/回流 导致的无限卡顿:
-
在 Performance 面板录制时,勾选 "Screenshot" 。
-
看帧率(FPS)图表,如果帧率极低且 Main 线程下有大量紫色的 "Rendering" 或 "Layout" 色块。
-
排查点:
- 检查
scroll事件里是否做了offsetTop/getBoundingClientRect计算,并且计算后又修改了style.top,导致浏览器陷入"修改-回流-再修改-再回流"的强制同步布局死循环。
- 检查
第五刀:环境干扰(最容易被忽略)
如果代码逻辑看着完美,换个浏览器就正常:
-
开启 无痕模式(Incognito) 复现。
- 如果无痕模式正常:浏览器插件(如翻译插件、油猴脚本)注入的代码搞崩了页面,逐个禁用排查。
-
打开 Network(网络) 面板,看是否有某个请求(如
sockjs-node热更新或超大json接口)一直处于 Pending(挂起) 状态,且阻塞了DOMContentLoaded事件。如果是,干掉这个超时请求。
终极保底手段(线上救急)
如果以上操作时页面已经完全点不动,不要关闭当前标签页:
- 打开一个新的浏览器标签页,输入
chrome://inspect/#pages(Edge 同理)。 - 找到你卡住的页面,点击 "inspect" ,这会另开一个独立的调试窗口,直接抓取卡死现场的堆栈信息,比在卡顿界面硬点 F12 成功率高出 90%。