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

HTML解析器在哪个阶段决定文档模式?
浏览器在读取到第一个非空白字符时就启动解析,而DOCTYPE必须出现在最前面——它不是可选的“建议”,而是触发标准模式的硬性开关。如果缺失或格式错误(比如写成小写、或带空格<code>),解析器会立即降级为怪异模式(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不是简单地“补上”,而是依据HTML标准第8.2.5.4节的栈式状态机规则动态修正。常见现象包括:
<p>Hello</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5493" title="html-to-pptx"><img src="https://img.php.cn/upload/skill/000/000/081/179051045119472.jpg" alt="html-to-pptx" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5493" title="html-to-pptx" class="overflowclass">html-to-pptx</a> <p class="overflowclass">将多页 HTML 演示文稿转换为美化的 PPTX 文件,便于分享和分发。</p> </div> <a rel="nofollow" href="/xiazai/skill5493" title="html-to-pptx" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <div>World → 自动闭合<code>p,再把div作为body子节点(而非p的子节点)-
<table><tr><td>A</td></tr></table>→ 插入隐式tbody,并在/table时终止tr和td - 遇到
但栈顶是div→ 直接忽略该结束标签,不报错也不弹栈 - 只扫描
head和body开头部分,遇到script阻塞就会暂停 - 无法识别
srcset或data-src这类非标准属性 -
async或defer脚本仍由主解析器控制执行时机
这种修复能力是双刃剑:它让页面“看起来能用”,但也掩盖了结构缺陷,导致CSS选择器失效或JS查询不到预期节点。
预解析器(Preload Scanner)和主解析器如何协作?
主解析器忙于Token化和建树时,预解析器会并行扫描尚未构建DOM的HTML片段,提前发现link rel="stylesheet"、script src、img src等资源并发起请求。但它不执行JS、不解析CSS内容、不触发DOM事件——只做“资源发现”。关键限制:
这意味着把关键CSS放head末尾、把非首屏JS放body底部,依然可能错过预加载窗口——真正影响首屏性能的是它们在HTML流中的物理位置,而不是语义重要性。










