预扫描器仅扫描html前6层dom深度且不解析js或条件逻辑,导致深层嵌套、js挂载、内、data-src及错误preload等资源无法被识别。

预扫描器根本看不到深层嵌套里的资源
Chromium 的预扫描器只扫描 HTML 字节流的前 6 层 DOM 深度,超出即截断。它不递归、不解析 JS、不展开 <template></template> 或 <slot></slot>,更不会执行条件逻辑。
常见失效现象包括:首屏大图始终是 Medium 优先级、LCP 候选元素请求延迟、link rel="preload" 声明了字体却仍 FOUC。
-
<picture></picture>被包在六层<div class="lazy-wrapper"> 里 → 预扫描器跳过整个节点 <li> <code><img>写在<details></details>或<dialog></dialog>内部 → 标签名都未被读到 - SSR 输出中关键图片由 JS hydration 后挂载 → 初始字节流里根本没有该标签
-
as="script"写成as="fetch"→ 请求走低优先级通道,后续<script src></script>无法复用,重复下载 -
as="font"却漏掉crossorigin→ 浏览器静默丢弃,FOIT 照旧 -
as="style"用于预加载 JS 文件 → 样式解析器拒绝处理,资源进不了样式表缓存 -
<link rel="preload" href="/hero.webp" as="image">若实际<img src="/HERO.WEBP">→ 路径不匹配,preload 失效 - 把
<img fetchpriority="high">放在{isLoaded && <img ...>}条件块里 → SSR 输出无此标签,预扫描器根本看不见 - 用
<div style="background-image: url(...)"> 承载 LCP → <code>fetchpriority对 CSS 背景图无效 - 同时设
loading="lazy"和fetchpriority="high"→ Chrome 115+ 中 lazy 行为会被降级,但 Safari/Firefox 仍按 lazy 处理 -
<img>→ 预扫描器只看到空src或缺失src,不触发请求 -
document.createElement('img').src = '/hero.jpg'→ JS 执行阶段才插入,晚于预扫描器工作时间 -
<noscript><img src="/fallback.jpg"></noscript>→ 预扫描器跳过整个<noscript></noscript>块 - Vue 的
v-if或 React 的{condition && <img>}→ SSR 输出中无该节点,预扫描器无从识别
link rel="preload" 放错位置或写错 as 就等于没写
link rel="preload" 必须出现在 或 开头附近,且 href 值要和最终 <img src> 完全一致(大小写、斜杠、查询参数都不能差);as 属性不是装饰,而是调度依据。
写错 as 的后果比你想象得更直接:浏览器按错误类型处理资源,可能降级、静默忽略、或无法复用。
fetchpriority="high" 不是万能钥匙,且支持度极有限
fetchpriority="high" 是 Chromium 101+ 引入的调度提示,仅对 <img> 和 <iframe></iframe> 生效,Safari 17.2+ 仅部分识别 <img>,Firefox 完全忽略。它不能替代 link rel="preload",也不能修复结构问题。
最常被误用的场景,是把它当成“强制提前加载”的开关,而忽略了它依赖预扫描器先看到该标签这一前提。
JS 动态插入、data-src、<noscript></noscript> 全部绕过预扫描器
预扫描器只看初始 HTML 字节流,不执行 JS,不解析 CSS,也不进入 <noscript></noscript> 或 <script type="application/json"></script> 内容。任何依赖运行时逻辑的资源声明,对它来说都不存在。
这意味着,哪怕你用 IntersectionObserver 精准控制加载时机,只要图片不在初始 HTML 里,就错过了预扫描器发现它的唯一窗口。
src、href 和 as。所有靠 JS、CSS、条件渲染、深度嵌套来“藏资源”的做法,本质上都是在对抗它的设计边界。











