HTML解析本身不慢,慢的是它被脚本和样式打断——优化核心不是“怎么快”,而是“怎么不被卡”。因为浏览器解析HTML是单线程、顺序进行的,未加修饰的<script>会立即暂停解析下载执行,<link rel="stylesheet">后紧跟脚本会强制串行等待CSS加载,@import引发三级串行阻塞,超并发请求排队导致解析“假卡顿”,这些中断而非解析本身造成性能瓶颈。

HTML解析本身不慢,慢的是它被脚本和样式打断——优化核心不是“怎么快”,而是“怎么不被卡”。
为什么<script>放在<head里会让首屏变白屏</script>
浏览器解析HTML时,遇到没有async或defer的<script>会立刻暂停DOM构建,去下载、解析、执行JS。此时即使HTML后面还有大量可见内容,也得干等着。
- 同步脚本在
<head>中,等于给整个DOM树“上锁”,用户看到的就是空白或闪烁的加载态 - 哪怕只是
console.log('hi'),只要没加defer,也会阻塞解析 - 第三方SDK(如埋点、广告)常默认同步加载,是白屏主因之一
如何用defer/async选对加载时机
defer和async都让脚本不阻塞HTML解析,但执行时机完全不同,选错反而引发DOM访问错误。
-
defer:脚本下载与HTML解析并行,执行时机在DOMContentLoaded前,且按书写顺序执行 —— 适合依赖DOM结构的初始化逻辑,比如document.getElementById调用 -
async:脚本下载完立刻执行,不保证顺序,也不等DOM就绪 —— 只适合完全独立、无DOM依赖的代码,如统计脚本tracker.js - 千万别对同一个文件同时写
async defer,后者会被忽略
CSS加载慢为何拖累JS执行
即使CSS不阻塞HTML解析,它仍会阻塞JS执行——浏览器必须等CSSOM就绪,才允许运行同步脚本,否则样式未定就操作DOM,可能导致布局抖动或重排失效。
立即学习“前端免费学习笔记(深入)”;
-
<link rel="stylesheet">会触发“CSS阻塞JS”行为,尤其当它出现在JS之前时 - 把
<script>移到</body>前,只能避开HTML阻塞,但无法绕过CSSOM依赖 - 媒体查询可缓解:加
media="print"或media="(max-width: 0)"的样式表,浏览器会异步加载,不参与渲染阻塞
内联
内联确实省了HTTP请求,但代价是HTML体积膨胀,TTFB(Time to First Byte)变长,且服务端返回更慢——对首屏渲染未必有利。
- 小量关键CSS(如首屏按钮、标题样式)可内联,但超过1KB就该拆出外部文件
- 内联JS若含大量逻辑或依赖第三方库,反而延长HTML解析时间,且无法被缓存
- 服务端渲染(SSR)场景下,内联资源可能干扰流式传输,导致浏览器无法边收边解
真正影响解析流畅度的,从来不是标签写法有多“标准”,而是你有没有让浏览器在合适的时间拿到合适的东西——解析器不会等你,它只认顺序和属性。



















