HTML解析是流式、自上而下的,结构顺序即渲染顺序:浏览器边下载边解析,遇<script>或阻塞<link rel="stylesheet">即暂停;源码顺序决定DOM生成、CSSOM构建及首屏绘制时机,首屏内容必须前置且避免被后续资源拖慢。

HTML 解析是流式、自上而下的,结构顺序 = 渲染顺序
浏览器一边下载 HTML,一边逐行解析构建 DOM 树,遇到 <script> 或阻塞的 <link rel="stylesheet"> 就暂停。这意味着:你在源码里写的顺序,直接决定 DOM 节点生成顺序、CSSOM 构建时机、首屏内容何时可绘制。
常见错误现象:document.getElementById("main") 返回 null,不是 JS 写错了,而是脚本执行时 <div id="main"> 还没解析到——它在脚本下方。
- DOM 构建必须完成,
DOMContentLoaded才触发;但若上方有未加载完的 CSS,即使 DOM 已就绪,页面仍白屏(CSSOM 阻塞渲染) -
<script>放在</body>前 ≠ 安全:它仍会同步下载,弱网下拖慢整个 HTML 流式解析 - 用
document.write()动态插入内容?它会清空当前文档,且只在解析阶段有效——现代项目基本该禁用
关键资源位置错位,首屏结构直接“失序”
结构优先级不是靠 CSS 视觉排版决定的,而是靠 HTML 中标签出现的物理位置。把 banner 图片写在页脚位置,哪怕用 position: fixed 拉到顶部,对首屏 LCP(最大内容绘制)毫无帮助——浏览器根本不会提前调度它。
使用场景:你希望用户第一眼看到 <header> 和 <main class="hero">,那它们就必须出现在 HTML 文件靠前位置,且不被后续大块 JS 或未优化 CSS 拖住。
立即学习“前端免费学习笔记(深入)”;
-
<link rel="stylesheet">必须在<script>之前,否则 script 执行时 CSSOM 可能未就绪,导致getComputedStyle返回空值 - 用
@import引入 CSS?它强制串行加载,会让后续所有样式规则延迟数百毫秒,首屏结构渲染卡顿 - 内联首屏 CSS 是最稳的方案,但只应包含
.hero、.nav等真正影响首屏结构的规则,别把.modal或.footer的样式也塞进去
loading="lazy" 对首屏结构完全无效,还可能拖慢 LCP
浏览器规范明确:所有初始视口内的 <img>,无论是否写了 loading="lazy",都会立即加载。加了只是白写,甚至干扰资源调度优先级。
容易踩的坑:有人为“统一管理”给所有图片加 loading="lazy",结果 banner 图片加载延迟 400ms,LCP 直接超标。
- 首屏图片必须显式设
loading="eager"或干脆不写(默认即 eager) - 非首屏图片才加
loading="lazy",且必须同时声明width和height,否则布局跳动(CLS) -
<iframe>支持loading="lazy",但 Safari 15.4 之前不支持,旧环境得 fallback 到data-src+IntersectionObserver
preload 写错位置或 as 值,结构加载反而更慢
<link rel="preload"> 不是插在任意位置都生效——它必须在 <head> 中、<meta charset> 和 <title> 之后、对应资源标签之前。放错地方,浏览器压根不认。
性能影响:写错 as 值会导致重复请求或低优先级下载。比如字体写成 as="fetch",Chrome 会按普通 fetch 处理,跨域失败;CSS 写成 as="script",会被当成 JS 下载,无法参与 CSSOM 构建。
- 字体预加载必须带
crossorigin:<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> - 不要对
loading="lazy"的图片再preload:部分 Chrome 版本会降级或丢弃该指令,造成策略冲突 - 验证是否生效:打开 Chrome DevTools → Network 面板,看预加载资源的 Priority 是否为
high



















