跳转到内容

预获取

页面加载时间在网站的可用性和整体体验中扮演着重要角色。当你的访问者与网站进行交互时,Astro 的可选预获取功能能在你的多页面应用(MPA)中带来几乎瞬时的页面导航的好处。

你可以使用 prefetch 配置来启用预获取:

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

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

<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>

每种策略都经过了微调,只有在需要时才预获取,以节省用户的带宽。例如:

  • 如果访问者使用流量节省模式或者有慢速连接,则预获取策略将会回退到 “tap” 策略。
  • 快速悬停或滚动链接不会预获取它们。

添加 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('/about', { ignoreSlowConnection: true });

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

与视图过渡动画一起使用

段落标题 与视图过渡动画一起使用

当你在页面上使用 视图过渡动画 时,预获取也将默认启用。它设置了一个默认配置 { prefetchAll: true },在页面上启用 所有链接的预获取

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

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// 完全禁用预获取
prefetch: false
});
astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// 保留预获取,但只对带有 `data-astro-prefetch` 的链接进行预获取
prefetch: {
prefetchAll: false
}
});

如果浏览器支持,Astro 的预获取将使用 <link rel="prefetch">,否则将回退到 fetch() API

常见的浏览器对 Astro 的预获取支持存在细微差别:

Chrome 支持 <link rel="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 迁移

段落标题 从 @astrojs/prefetch 迁移

@astrojs/prefetch 集成在 v3.5.0 中被弃用,最终将被完全移除。使用以下说明将 @astrojs/prefetch 迁移到 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"

      <!-- 如果 `defaultStrategy` 设置为 `hover`(默认),你可以省略值 -->
      <a href="/about" data-astro-prefetch>
      <!-- 否则,你可以明确定义预获取策略 -->
      <a href="/about" data-astro-prefetch="hover">
    • @astrojs/prefetchthrottles 选项不再需要,因为新的预获取特性将自动调度和优化预获取。

贡献

你有什么想法?

社区