跳转到内容

预取

页面加载时间在网站的可用性和整体体验中扮演着重要角色。Astro 的选择性加入预取功能,可以在访问者与你的多页应用(MPA)交互时,为他们带来近乎即时的页面导航体验。

你可以通过 prefetch 配置来启用预取功能

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
prefetch: true
});

一个预取脚本将被添加到你网站的所有页面。然后,你可以将 data-astro-prefetch 属性添加到网站上的任何 <a /> 链接中,以选择性地启用预取。当您将鼠标悬停在链接上时,该脚本将在后台获取页面。

<a href="/about" data-astro-prefetch>

请注意,预取仅适用于你网站内部的链接,不适用于外部链接。

prefetch 配置也接受一个选项对象以进一步自定义预取。

Astro 支持 4 种预取策略,以适应不同的使用场景

  • hover(默认):当您悬停或聚焦在链接上时进行预取。
  • tap:在您点击链接之前进行预取。
  • viewport:当链接进入视口时进行预取。
  • load:页面加载后,预取页面上的所有链接。

你可以通过将策略传递给 data-astro-prefetch 属性来为单个链接指定策略

<a href="/about" data-astro-prefetch="tap">About</a>

每种策略都经过微调,仅在需要时进行预取,以节省用户的带宽。例如

添加 data-astro-prefetch 属性时的默认预取策略是 hover。要更改它,你可以在你的 astro.config.mjs 文件中配置prefetch.defaultStrategy

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
prefetch: {
defaultStrategy: 'viewport'
}
});

如果你想预取所有链接,包括那些没有 data-astro-prefetch 属性的链接,你可以将prefetch.prefetchAll设置为 true

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
prefetch: {
prefetchAll: true
}
});

然后,你可以通过设置 data-astro-prefetch="false" 来为单个链接选择退出预取

<a href="/about" data-astro-prefetch="false">About</a>

所有链接的默认预取策略可以通过 prefetch.defaultStrategy 进行更改,如默认预取策略部分所示。

由于某些导航可能不总是以 <a /> 链接的形式出现,你也可以使用 astro:prefetch 模块中的 prefetch() API 以编程方式进行预取

<button id="btn">Click me</button>
<script>
import { prefetch } from 'astro:prefetch';
const btn = document.getElementById('btn');
btn.addEventListener('click', () => {
prefetch('/about');
});
</script>

prefetch() API 包含了相同的省流模式慢速连接检测,因此它只在需要时进行预取。

要忽略慢速连接检测,你可以使用 ignoreSlowConnection 选项

// Prefetch even on data saver mode or slow connection
prefetch('/about', { ignoreSlowConnection: true });

类型: 'immediate' | 'eager' | 'moderate' | 'conservative'
默认值: 'immediate'

添加于: astro@5.6.0

在启用实验性clientPrerender标志后,你可以在 prefetch() 上使用 eagerness 选项,向浏览器建议它应该以多大的“渴望度”来预取/预渲染链接目标。

这遵循 Speculation Rules API 中描述的相同 API,并默认为 immediate(最“渴望”的选项)。按渴望度降序排列,其他选项是 eagermoderateconservative

eagerness 选项允许你在减少等待时间的好处与网站访问者的带宽、内存和 CPU 成本之间取得平衡。一些浏览器,如 Chrome,已经设置了限制以防止过度推测(预渲染/预取太多链接)。

---
---
<script>
// Control prefetching eagerness with `experimental.clientPrerender`
import { prefetch } from 'astro:prefetch';
// This page is resource-intensive
prefetch('/data-heavy-dashboard', { eagerness: 'conservative' });
// This page is critical to the visitor's journey
prefetch('/getting-started'); // defaults to `{ eagerness: 'immediate' }`
// This page may not be visited
prefetch('/terms-of-service', { eagerness: 'moderate' });
</script>

要在大量链接上以编程方式使用 prefetch(),你可以设置 eagerness: 'moderate',以利用先进先出(FIFO)策略和浏览器启发式算法,让浏览器决定何时以及以何种顺序预渲染/预取它们

<a class="link-moderate" href="/nice-link-1">A Nice Link 1</a>
<a class="link-moderate" href="/nice-link-2">A Nice Link 2</a>
<a class="link-moderate" href="/nice-link-3">A Nice Link 3</a>
<a class="link-moderate" href="/nice-link-4">A Nice Link 4</a>
...
<a class="link-moderate" href="/nice-link-20">A Nice Link 20</a>
<script>
import { prefetch } from 'astro:prefetch';
const linkModerate = document.getElementsByClassName('link-moderate');
linkModerate.forEach((link) => prefetch(link.getAttribute('href'), {eagerness: 'moderate'}));
</script>

确保只在客户端脚本中导入 prefetch(),因为它依赖于浏览器 API。

当你在页面上使用Astro 的 <ClientRouter /> 时,预取也将默认启用。它会设置一个默认配置 { prefetchAll: true },从而为页面上的所有链接启用预取

你可以在 astro.config.mjs 中自定义预取配置来覆盖默认值。例如

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// Disable prefetch completely
prefetch: false
});
astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// Keep prefetch, but only prefetch for links with `data-astro-prefetch`
prefetch: {
prefetchAll: false
}
});

Astro 的预取功能在浏览器支持的情况下使用 <link rel="prefetch">,否则回退到 fetch() API

最常见的浏览器都支持 Astro 的预取功能,但存在细微差别

Chrome 支持 <link rel="prefetch">。预取功能按预期工作。

它还完全支持来自 Speculation Rules API<script type="speculationrules">,可用于进一步描述预取策略和规则,从而增强 Chrome 用户的体验。你需要启用clientPrerender实验性功能才能在 prefetch() 中使用此功能

Firefox 支持 <link rel="prefetch">,但可能会显示错误或完全失败

  • 如果没有显式的缓存头(例如 Cache-ControlExpires),预取将报错 NS_BINDING_ABORTED
  • 即使发生错误,如果响应具有正确的 ETag 头,它也将在导航时被重用。
  • 否则,如果它在没有其他缓存头的情况下出错,预取将无法工作。

Safari 不支持 <link rel="prefetch">,将回退到 fetch() API,这需要设置缓存头(例如 Cache-ControlExpiresETag)。否则,预取将无法工作。

边缘情况: ETag 标头在隐私窗口中不起作用。

为了最好地支持所有浏览器,请确保你的页面具有正确的缓存头。

对于静态或预渲染的页面,ETag 头通常由部署平台自动设置,并有望开箱即用。

对于动态和服务器端渲染的页面,请根据页面内容自行设置适当的缓存头。请访问 MDN 关于 HTTP 缓存的文档以获取更多信息。

@astrojs/prefetch 集成已在 v3.5.0 中被弃用,并将最终被完全移除。请按照以下说明迁移到 Astro 的内置预取功能,该功能取代了此集成。

  1. 移除 @astrojs/prefetch 集成,并在 astro.config.mjs 中启用 prefetch 配置

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import prefetch from '@astrojs/prefetch';
    export default defineConfig({
    integrations: [prefetch()],
    prefetch: true
    });
  2. @astrojs/prefetch 的配置选项转换

    • 已弃用的集成使用 selector 配置选项来指定哪些链接在进入视口时应被预取。

      请改为向这些单独的链接添加 data-astro-prefetch="viewport"

      <a href="/about" data-astro-prefetch="viewport">
    • 已弃用的集成使用 intentSelector 配置选项来指定哪些链接在被悬停或聚焦时应被预取。

      请改为向这些单独的链接添加 data-astro-prefetchdata-astro-prefetch="hover"

      <!-- You can omit the value if `defaultStrategy` is set to `hover` (default) -->
      <a href="/about" data-astro-prefetch>
      <!-- Otherwise, you can explicitly define the prefetch strategy -->
      <a href="/about" data-astro-prefetch="hover">
    • 来自 @astrojs/prefetchthrottles 选项不再需要,因为新的预取功能将自动进行最佳的调度和预取。

贡献 社区 赞助