preload scanner 遇到无 defer/async 的阻塞脚本或超大内联 script 会立即终止扫描,导致后续资源漏加载。它仅识别静态 src 属性,无视 srcset、模板变量、js 动态插入及 css @import,且依赖 html 中资源标签的物理顺序与合法性。

Preload Scanner 为什么只扫到一半就停了
浏览器在开始解析 HTML 之前,会先启动一个轻量级的预扫描器(Preload Scanner),它不构建 DOM,只快速向前查找 <link rel="preload">、<script src></script>、<img src> 等资源声明,提前发起网络请求。但它**不会执行 JS、不解析 CSS、也不深入嵌套结构**——一旦遇到阻塞型 <script></script>(没加 defer 或 async),它就立刻终止。
常见错误现象:<script src="vendor.js"></script> 放在 开头,结果预扫描器扫完这行就停,后面 <link rel="preload" as="font"> 和首屏 <img> 全被漏掉;或者内联 <script>window.__INIT__ = {...}</script> 体积超 2KB,直接卡住预扫描。
-
<script></script>必须带defer或async才允许预扫描器跨过它继续向前 - 内联脚本超过 ~1KB 就有高概率中断预扫描,建议拆成外链 +
defer -
<link rel="preload">要尽可能靠近开头,别被无关<meta>或注释隔开 - 不要把
<script></script>放在<link rel="preload">前面——顺序就是加载优先级
为什么
没被预扫描器识别
预扫描器只识别 src 属性,对 srcset、sizes、data-src 完全无视。这意味着:如果你写的是 <img srcset="a-400.jpg 400w, a-800.jpg 800w" sizes="..."> 但没写 src,预扫描器根本看不到这张图,也不会提前请求任何版本。
使用场景:首屏响应式图片必须提供 fallback src,哪怕只是占位符,否则无法触发预加载;非首屏图可放心用 loading="lazy" + srcset 组合,因为懒加载不依赖预扫描器。
- 首屏
<img>必须含src(哪怕指向 1px GIF),才能被预扫描器捕获 -
srcset的实际选择由主解析器在 DOM 构建后决定,和预扫描无关 - 用
<picture></picture>包裹时,预扫描器只认最外层<img src>,不读<source></source> - 避免用 JS 动态设置
src——预扫描器跑完时 JS 还没执行,等于“不存在”
哪些 HTML 结构会让 Preload Scanner “视而不见”
预扫描器是纯文本流式扫描,它不理解语义、不解析属性值、不执行条件逻辑。很多看似正常的写法,在它眼里就是“不可见”。
常见错误现象:CSS 中写 @import "fonts.css";,预扫描器完全忽略;<link href="%7B%7BcssUrl%7D%7D">(模板变量)被当成普通字符串;<script>document.write('<img src="x.jpg">')</script> 生成的 <img> 永远不会被预扫描。
-
@import在 CSS 文件里 —— 预扫描器只扫 HTML,不进 CSS 文件 - 模板语法如
{{url}}、—— 扫描器当作文本,不是有效属性值 - JS 动态插入的标签(
el.innerHTML = '<img src>')—— 发生在预扫描之后 -
<iframe src="..."></iframe>不会被预扫描器抓取资源,除非显式写<link rel="preload" as="document" href="...">
怎么验证 Preload Scanner 是否按预期工作
不能靠“写了就生效”,得看浏览器实际发了哪些请求、何时发的。Chrome DevTools 的 Network 面板是最直接证据,但要注意筛选条件。
关键判断点:所有被预扫描器捕获的资源,请求发起时间必须早于 DOMContentLoaded,且在 document.write 或第一个 JS 执行前就已出现在 Network 列表中。
- 打开 DevTools → Network → 刷新页面 → 按 Initiated By 列排序,找标记为
Parser的请求(不是Other或Script) -
<link rel="preload">请求应显示 Priority:High;普通<link rel="stylesheet">是Medium - 如果某张首屏图的请求 Initiated By 是
Other,说明没被预扫描,可能缺src或被阻塞脚本截断 - 禁用 JS 后重刷:若资源请求消失,说明原本依赖 JS 注入,不是预扫描器发现的
真正影响预扫描效果的,从来不是你写了多少 preload,而是 HTML 结构有没有给它留出“一口气扫到底”的机会——空格、注释、未加属性的 <script></script>、模板变量,都是隐形断点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











