HTML解析器在Tokenizer词法分析阶段初启时即决定文档模式,DOCTYPE必须位于文件最开头,缺失或格式错误(如小写doctype、前置空格)会立即触发怪异模式,影响后续Tree Construction的容错逻辑与渲染行为。

HTML解析器在哪个阶段决定文档模式?
浏览器在读取到第一个非空白字符时就启动解析,而DOCTYPE必须出现在最前面——它不是可选的“建议”,而是触发标准模式的硬性开关。如果缺失或格式错误(比如写成<!doctype html>小写、或带空格<! DOCTYPE html>),解析器会立即降级为怪异模式(Quirks Mode)。此时Tree Construction阶段的容错规则完全不同:表格嵌套逻辑、盒模型计算、甚至document.body的初始化时机都会偏移。
为什么meta charset必须放在head靠前位置?
Tokenizer阶段需要知道用什么编码解码后续字节流,而meta charset是它唯一能主动识别的编码声明方式(HTTP响应头Content-Type优先级更高,但不可控)。如果把它放在title后面、或者包裹在script里,Tokenizer早已按默认编码(通常是ISO-8859-1)解析了前面几百字节,导致中文变乱码、属性值截断、甚至标签名识别失败。实操中务必保证:<meta charset="utf-8">是head内第一个或第二个标签,且不能被JS动态插入。
树构建器如何处理未闭合标签?
Tree Construction不是简单地“补上</div>”,而是依据HTML标准第8.2.5.4节的栈式状态机规则动态修正。常见现象包括:
-
<p>Hello<div>World</p>→ 自动闭合p,再把div作为body子节点(而非p的子节点) -
<table><tr><td>A</table>→ 插入隐式tbody,并在/table时终止tr和td - 遇到
</p>但栈顶是div→ 直接忽略该结束标签,不报错也不弹栈
这种修复能力是双刃剑:它让页面“看起来能用”,但也掩盖了结构缺陷,导致CSS选择器失效或JS查询不到预期节点。
立即学习“前端免费学习笔记(深入)”;
预解析器(Preload Scanner)和主解析器如何协作?
主解析器忙于Token化和建树时,预解析器会并行扫描尚未构建DOM的HTML片段,提前发现link rel="stylesheet"、script src、img src等资源并发起请求。但它不执行JS、不解析CSS内容、不触发DOM事件——只做“资源发现”。关键限制:
- 只扫描
head和body开头部分,遇到script阻塞就会暂停 - 无法识别
srcset或data-src这类非标准属性 -
async或defer脚本仍由主解析器控制执行时机
这意味着把关键CSS放head末尾、把非首屏JS放body底部,依然可能错过预加载窗口——真正影响首屏性能的是它们在HTML流中的物理位置,而不是语义重要性。



















