写过 MPA 的人都踩过这个坑——点一个链接,等了 1 秒白屏——今天这件事被一个 JSON 彻底原生化了
写过 MPA 的人都踩过这个坑——点一个链接,等了 1 秒白屏才知道内容出来了。网络再好也逃不掉,因为 prefetch 只帮你提前下载了 HTML,浏览器还是要重新解析、渲染、执行一遍。今天 Chrome 用一个 API 把这件事彻底原生化了。
它做了什么
Speculation Rules API 允许浏览器在用户点击之前,就在后台把下一个页面的完整生命周期跑完——HTML 解析、CSS 渲染、JS 执行全部在隐藏标签页里完成。用户点击的一瞬间,页面已经准备好了,直接激活就行。激活这一步几乎没有感知延迟,LCP 直接掉到接近零。
对比一下:
- prefetch:只下载 HTML,用户点击后浏览器才开始解析渲染,依然要等
- prerender:完整跑完页面生命周期,点击即呈现,接近零延迟
对于有明确导航路径的场景(博客列表→文章、产品页→详情页),prerender 的性能提升是最直接的。
怎么写
声明式 JSON,塞进一个 <script type="speculationrules">:
<script type="speculationrules">
{
"prerender": [{
"where": { "href_matches": "/articles/*" },
"eagerness": "moderate"
}],
"prefetch": [{
"urls": ["/checkout", "/cart"],
"eagerness": "conservative"
}]
}
</script>
eagerness 控制触发时机:
- conservative:等到用户按下鼠标/触摸才开始,提前 50~200ms,几乎没有浪费
- moderate:悬停 200ms 后触发,提前 200~800ms,大部分场景的甜区
- eager:链接一进入视口就开始,提前时间最长但浪费带宽风险最大
where 支持 URL pattern 和 CSS selector 组合,比旧的 <link rel="prefetch"> 强大得多。
两个必须知道的坑
第一,不要 prerender 有副作用的页面。 结算页、登出页、带一次性 token 的链接,这些页面的逻辑会在 prerender 时执行,而不是用户真正到达时执行。Chrome 会静默丢弃这些副作用,但你的后端日志会混乱。
{
"prerender": [{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": { "href_matches": "/logout*" } },
{ "not": { "href_matches": "/checkout*" } },
{ "not": { "selector_matches": ".no-prerender" } }
]
},
"eagerness": "moderate"
}]
}
第二,内存不是无限的。 Chrome 对并行 prerender 数量有上限,超出后会按时间顺序丢弃最老的。和真实页面一样,十个并行 prerender 约等于渲染十个 iframe,对移动端有感知量的用户来说这是流量成本,对服务器来说这是额外的数据库查询和算力消耗。
真实案例:某文档站测试 moderate eagerness,在 4 万日活页面上,68% 的导航确实被正确预测,32% 的 prerender 属于浪费带宽。但因为 Chrome 会主动淘汰低优先级 prerender,实际内存压力比预想的可控。
Astro 6 一行开启
Astro 6 内置了 clientPrerender 实验特性,三行配置:
// astro.config.mjs
export default defineConfig({
experimental: {
clientPrerender: true
}
})
Astro 自动为站内链接生成 prerender 规则,多页面站配合 View Transitions 可以做到 SPA 级别的导航体验,而不需要引入 React 的 85~150KB 水合成本。
测什么指标
不要测「prerender 花了多久」——用户根本看不到这个数字。
测真实导航场景下的 Core Web Vitals(CrUX 或 RUM):
- LCP:接近 0ms(页面已渲染好)
- INP:从 98~145ms 降到 62~88ms(用户点击后无等待)
- TTFB:基本不变(服务端处理逻辑照旧)
浏览器现状
- Chrome 109+ / Edge 109+:完整支持 prerender + prefetch + document rules
- Safari / Firefox:gracefully ignore,什么都不发生
- 全球覆盖率:~68~70%
因为是纯渐进增强,Safari/Firefox 用户体验和没有这个 API 时完全一样,不存在降级问题。
三句话总结
Prefetch 只解决了「下载」问题,prerender 把整个页面的渲染都提前跑完了;写几条 JSON 就能给多页面站加上「点击即呈现」的体验,不用改一行业务代码;用 moderate eagerness 起步,排除有副作用的页面,测 INP 而不是 prerender 耗时。
评论区
登录后可评论。