html解析器采用流式处理,边接收字节边构建dom树,依赖状态机进行词法分析,具备容错修复能力,但受脚本阻塞、编码声明缺失、标签误写等因素影响。

HTML解析器从字节流开始,不是等完整文件才动手
浏览器根本不会等整个HTML下载完再开始干活。你看到的“页面一点点加载出来”,本质就是解析器边收字节边建树。只要第一个到达,解析就启动了——这和你在终端里用cat管道传内容给grep类似,是流式处理。
常见错误现象:本地双击打开index.html时页面空白或样式错乱,往往是因为解析中途遇到未闭合标签或编码声明缺失(比如没写<meta charset="utf-8">),导致后续token识别错位,DOM树构建异常。
- 必须在
最开头声明<meta charset>,否则早期字节可能被误判为ASCII,中文变乱码 - 服务器返回的
Content-Type响应头带charset参数(如text/html; charset=utf-8)优先级高于HTML内声明 - 遇到
<script></script>且无async或defer时,解析会暂停,直到脚本下载、执行完毕——这是阻塞点,也是首屏延迟主因之一
词法分析阶段生成Token,状态机决定每个字符怎么解读
解析器内部是个状态机,遇到就切到“标签开始”态,接着读字母就认为是开始标签,读<code>/就转成结束标签态,读!则可能进入注释或DOCTYPE处理分支。这个过程不依赖正则,而是靠有限状态自动机逐字符推进。
容易踩的坑:手写HTML时用中文全角符号(如<、/)会被当成普通文本节点,无法触发标签逻辑;或者在属性值里漏掉引号,像<div class="header">,当后面紧跟<code><span></span>时,解析器可能把span误判为class的值。
-
<!-- comment -->是合法Token,但会被完全忽略,不进DOM树 - 自闭合标签如
<img>、<br>在HTML5中不需要/>,加了也不报错,但<div></div>这种写法会被当作<div></div>处理 - 遇到未知标签(如
<my-component></my-component>),浏览器照常建元素节点,只是没默认样式和语义
语法分析用栈构建DOM树,容错机制比你想象得更激进
DOM树不是严格按源码结构硬套出来的。浏览器会主动修复明显错误,比如<div><p></p></div>会被重排为<div><p></p></div>,因为解析器栈顶是<div>,遇到<code>











