HTML解析挂起和网页死锁是主线程被明确阻塞所致,如脚本未加async/defer会强制暂停解析,内联脚本立即挂起GUI线程,DOM频繁读写触发回流,长任务超50ms导致交互失联,未闭合标签引发浏览器强制重排。
HTML 解析挂起和网页死锁不是偶发卡顿,而是浏览器主线程被明确阻塞或持续占用的结果——只要出现白屏、按钮无响应、滚动冻结超过 300ms,基本可判定是解析或执行层面的硬性阻塞。
只要 <script src="xxx.js"></script> 出现在 <head> 里且没带 async 或 defer,浏览器就会暂停 HTML 解析,等脚本下载并执行完才继续。这不是“慢”,是解析器彻底停摆。
console.log(1),HTTP 请求本身也会触发阻塞<script>alert(1)</script> 这种内联脚本更狠:不走网络,但立刻执行、立刻挂起 GUI 线程JS 引擎和 GUI 渲染线程互斥。你在循环里反复读写 offsetHeight、style.left 或调用 document.getElementById(),每读一次都可能触发回流(reflow),每次回流都要等 JS 执行完才能画,结果就是“点了按钮没反应”“滚动卡成幻灯片”。
for 循环中查 DOM:const list = document.querySelectorAll('[id^="item-"]') 提前缓存class 切换,而不是逐个设 el.style.xxx
document.write()——它会清空当前文档并重建 parser,强制重排,现代浏览器已标记为废弃一个函数执行超过 50ms,浏览器就判定为“长任务”,用户交互事件(点击、输入)会被压在队列尾部,直到它跑完。常见于数据处理、字符串匹配、深度遍历等场景,不是报错,但页面彻底失联。
立即学习“前端免费学习笔记(深入)”;
setTimeout 或 requestIdleCallback 拆分任务,别让单次执行超 50msinit() 里做 DOM 遍历+计算,一上来就占满主线程一个漏掉的 </div> 可能导致后续几百行 HTML 全部被错误包裹。修复时容易陷入局部思维:看到 footer 跑进 header,第一反应是去修 header 末尾,其实问题可能出在前面第 3 个 <section> 漏了 </section>。
table、ul、ol 内部只接受特定子标签(如 tr、li),塞进 div 或 p 会直接触发重排,DOM 树立刻失真真正难排查的,是那些既不报错也不警告的阻塞:比如一个没加 defer 的第三方脚本,正好卡在首屏 DOM 构建中途;或者一段看似无害的循环读取 clientWidth,却在低端机上把帧率拉到 5fps。这类问题不会出现在 Console 里,得靠 Performance 面板里 Parse HTML 被 Evaluate Script 截断的痕迹来定位。