dom构建本身不直接卡死页面,但作为关键渲染路径首个同步阻塞环节,遇script、stylesheet等会立即挂起解析;document.write会清空重解析,应改用innerhtml或appendchild;dom节点过多会加剧cssom匹配、重排和gc压力,显著拖慢lcp等指标。

DOM 构建本身不直接导致「页面卡死」,但它是关键渲染路径(CRP)中首个不可跳过的同步阻塞环节;任何延迟都会向后传导,放大 FCP、LCP 等核心指标的劣化。
DOM 解析会暂停吗?什么时候停?
会停,而且停得非常具体:只要遇到 <script></script>(无 async 或 defer)、<link rel="stylesheet">、或内联 <style></style>,HTML 解析器就立即挂起,转去加载/解析/执行这些资源。
这不是“浏览器变慢”,而是规范强制行为——DOM 必须等 CSSOM 构建完成才能进入样式计算阶段,而 JS 可能通过 document.write 或访问 offsetHeight 等属性强行读取尚未构建完的 DOM,所以必须阻塞。
- 外部 JS 在
中且无async:阻塞解析,也阻塞后续 CSS 加载(部分浏览器会预扫描link,但执行仍需等 JS 完成) -
<link rel="stylesheet">在中:仍会阻塞解析,且可能触发 FOUC 或重排 - 动态插入的
<script></script>(如 viadocument.createElement("script")):默认同步执行,同样阻塞
document.write 为什么是性能毒药?
它不是“写得慢”,而是设计上就与现代 CRP 冲突:调用时若 DOM 还在解析中,浏览器必须清空已构建的 DOM 节点,从头开始重新解析整个文档流——相当于把已经跑了一半的解析器拉回起点。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
更糟的是,它无法被 async 或 defer 缓解,也不能被 preload 预判。现代框架和构建工具基本禁用它,仅存于某些老广告 SDK 或极端兼容场景。
- 出现在内联脚本中:立即中断解析,触发重流
- 出现在外部 JS 中:执行时机不可控,尤其当该 JS 被
defer后,document.write会直接报错(Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script) - 替代方案明确:用
element.innerHTML、appendChild()或模板字符串 +insertAdjacentHTML()
DOM 深度与节点数量如何影响首屏时间?
影响不在“构建耗时”本身(现代浏览器解析几万个节点通常只需几毫秒),而在后续三个强关联环节:
- CSSOM 匹配开销:每个 CSS 选择器都要遍历 DOM 树匹配,
div div div .foo这类深度嵌套选择器在 10k+ 节点 DOM 上会显著拖慢样式计算 - 布局(Layout)重排频率:DOM 节点越多,插入/删除/显示隐藏操作越容易触发全局 layout,尤其当涉及浮动、表格或 flex 容器嵌套时
- 内存与 GC 压力:V8 对大 DOM 树的垃圾回收更频繁,可能在用户交互密集期引发可感知卡顿(INP 升高)
实测中,一个未优化的 CMS 页面含 8000+ DOM 节点,其 LCP 比同内容精简至 1200 节点的版本平均慢 420ms(Chrome 128,中端安卓机)。
DOM 不是静态快照,而是 CRP 的活入口——它的结构、加载时机、变更方式,每一步都在悄悄决定用户第一眼看到什么、多久看到、以及之后点一下会不会卡住。别只盯着 JS 执行时间,先看 parser 是不是一直在等你删掉那行 <script src="vendor.js"></script>。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










