quicklink

quicklink

智能预取技术加速网页加载的轻量级库

quicklink 是一个智能预取库,用于优化网页加载性能。它自动检测视口中的链接,并在浏览器空闲时预取或预渲染,提高后续页面访问速度。适用于多页面和单页面应用,提供灵活的配置选项。quicklink 代码精简,压缩后仅 2KB,是一个高效的开源性能优化工具。

quicklink预取性能优化网页加载JavaScriptGithub开源项目
<p align="center"> <img src="https://yellow-cdn.veclightyear.com/835a84d5/effe6706-f03f-420a-8be6-77053bf524b0.png" alt="" width="640"> <br> <a href="https://www.npmjs.com/package/quicklink"> <img src="https://img.shields.io/npm/v/quicklink?style=flat&logo=npm&logoColor=fff" alt="npm"> </a> <a href="https://unpkg.com/quicklink"> <img src="https://img.shields.io/bundlephobia/minzip/quicklink" alt="gzip size"> </a> <a href="https://github.com/GoogleChromeLabs/quicklink/actions/workflows/ci.yml?query=workflow%3ACI+branch%3Amain"> <img src="https://img.shields.io/github/actions/workflow/status/GoogleChromeLabs/quicklink/ci.yml?branch=main&label=ci&logo=github" alt="ci"> </a> </p>

quicklink

通过在空闲时间预取或预渲染视口内的链接,实现后续页面加载更快

工作原理

Quicklink 试图使导航到后续页面的加载速度更快。它:

  • 检测视口内的链接(使用Intersection Observer
  • 等待浏览器空闲(使用requestIdleCallback
  • 检查用户是否处于慢速连接(使用navigator.connection.effectiveType)或启用了数据保护(使用navigator.connection.saveData
  • 预取(使用<link rel=prefetch>或XHR)或预渲染(使用Speculation Rules API)链接的URL。提供一些对请求优先级的控制(如果支持,可以切换到fetch())。

为什么

这个项目旨在为网站提供一个即插即用的解决方案,根据用户视口中的内容预取或预渲染链接。它还致力于保持小巧(压缩并gzip后小于2KB)。

多页应用

安装

对于Node.jsnpm

npm install quicklink

你也可以从unpkg.com/quicklink获取quicklink

使用

初始化后,quicklink将在空闲时自动预取视口内链接的URL。

快速开始:

<!-- 从dist引入quicklink --> <script src="dist/quicklink.umd.js"></script> <!-- 初始化(你可以在任何时候进行) --> <script> quicklink.listen(); </script>

例如,你可以在load事件触发后初始化:

<script> window.addEventListener('load', () => { quicklink.listen(); }); </script>

ES模块导入:

import {listen, prefetch} from 'quicklink';

单页应用(React)

安装

首先,使用Node.jsnpm安装包:

npm install quicklink webpack-route-manifest --save-dev

然后,按照这里的说明将Webpack路由清单配置到你的项目中。 这将生成一个名为rmanifest.json的路由和代码块映射。可以在以下位置获取:

  • URL:site_url/rmanifest.json
  • Window对象:window.__rmanifest

使用

在你想添加预取功能的地方导入quicklink React HOC。 用withQuicklink()HOC包装你的路由。

例子:

import {withQuicklink} from 'quicklink/dist/react/hoc.js'; const options = { origins: [], }; <Suspense fallback={<div>加载中...</div>}> <Route path='/' exact component={withQuicklink(Home, options)} /> <Route path='/blog' exact component={withQuicklink(Blog, options)} /> <Route path='/blog/:title' component={withQuicklink(Article, options)} /> <Route path='/about' exact component={withQuicklink(About, options)} /> </Suspense>;

API

quicklink.listen(options)

返回:Function

返回一个"重置"函数,该函数将清空活动的IntersectionObserver和已预取或预渲染的URL缓存。这可以在页面导航之间和/或发生重大DOM更改时使用。

options.prerender

  • 类型:Boolean
  • 默认值:false

是否从默认的预取模式切换到视口内链接的预渲染模式。

**注意:**当浏览器不支持预渲染时,预渲染模式(当此选项设置为true时)将回退到预取模式。

options.prerenderAndPrefetch

  • 类型:Boolean
  • 默认值:false

是否同时激活预取和预渲染模式。

options.delay

  • 类型:Number
  • 默认值:0

每个链接在被预取之前需要停留在视口内的时间,以毫秒为单位。

options.el

  • 类型:HTMLElement|NodeList<A>
  • 默认值:document.body

要观察的DOM元素,用于检测视口内需要预取的链接,或锚点元素的NodeList。

options.limit

  • 类型:Number
  • 默认值:Infinity

在观察options.el容器时可以预取或预渲染的总请求数。

options.threshold

  • 类型:Number
  • 默认值:0

每个链接必须进入视口的面积百分比才能被获取,以小数形式表示(例如,0.25 = 25%)。

options.throttle

  • 类型:Number
  • 默认值:Infinity

在观察options.el容器时,同时进行的请求数限制。

options.timeout

  • 类型:Number
  • 默认值:2000

requestIdleCallback超时时间,以毫秒为单位。

**注意:**浏览器必须在配置的持续时间内保持空闲状态才会进行预取。

options.timeoutFn

  • 类型:Function
  • 默认值:requestIdleCallback

用于指定timeout延迟的函数。

这可以替换为自定义函数,如networkIdleCallback(参见演示)。

默认情况下,使用requestIdleCallback或嵌入的polyfill。

options.priority

  • 类型:Boolean
  • 默认值:false

options.el容器内的URL是否应被视为高优先级。

当设置为true时,如果支持,quicklink将尝试使用fetch() API(而不是link[rel=prefetch])。

options.origins

  • 类型:Array<String>
  • 默认值:[location.hostname]

允许预取的URL主机名的静态数组。

默认为相同的域名源,这可以防止任何跨域请求。

重要:空数组([])允许预取所有来源

options.ignores

  • 类型:RegExpFunctionArray
  • 默认值:[]

确定是否应预取URL。

RegExp测试为正,Function返回true,或Array包含字符串时,则不会预取该URL。

注意:Array可以包含StringRegExpFunction值。

**重要:**此逻辑在源匹配之后执行!

options.onError

  • 类型:Function
  • 默认值:无

一个可选的错误处理函数,用于接收预取请求中的任何错误。

默认情况下,这些错误会被静默忽略。

options.hrefFn

  • 类型:Function
  • 默认值:无

一个可选函数,用于生成要预取的URL。它接收一个Element作为参数。

quicklink.prefetch(urls, isPriority)

返回:Promise

提供的urls始终通过Promise.all传递,这意味着结果将始终解析为一个数组。

**重要:**你必须自行catch请求错误。

urls

  • 类型:StringArray<String>
  • 必需:true

一个或多个要预取的URL。

**注意:**每个url值都是相对于当前位置解析的。

isPriority

  • 类型:Boolean
  • 默认值:false

是否将URL视为"高优先级"目标。

默认情况下,对prefetch()的调用为低优先级。

**注意:**这与listen()priority选项行为相同。

quicklink.prerender(urls)

返回:Promise

**重要:**你必须自行catch请求错误。

urls

  • 类型:StringArray<String>
  • 必需:true

一个或多个要预渲染的URL。

**注意:**推测性规则API支持同站跨域预渲染,需要选择加入头部

填充

quicklink

  • 包含一个非常小的requestIdleCallback回退
  • 需要支持IntersectionObserver(参见Can I Use)。我们建议使用Polyfill.io等服务有条件地填充此功能:
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>

或者,参见Intersection Observer polyfill

使用示例

为预取资源设置自定义超时

默认为2秒(通过requestIdleCallback)。这里我们将其覆盖为4秒:

quicklink.listen({ timeout: 4000, });

设置特定的锚元素NodeList以观察视口内的链接

默认为document

quicklink.listen({ el: document.querySelectorAll('a.linksToPrefetch'), });

设置DOM元素以观察视口内的链接

默认为document

quicklink.listen({ el: document.getElementById('carousel'), });

以编程方式prefetch() URL

如果你更喜欢提供一个静态的URL列表进行预取,而不是检测视口内的URL,支持自定义URL。

// 单个URL quicklink.prefetch('2.html'); // 多个URL quicklink.prefetch(['2.html', '3.html', '4.js']); // 多个URL,高优先级 // 注意:也可用于单个URL! quicklink.prefetch(['2.html', '3.html', '4.js'], true);

以编程方式prerender() URL

如果你更喜欢提供一个静态的URL列表进行预渲染,而不是检测视口内的URL,支持自定义URL。

// 单个URL quicklink.prerender('2.html'); // 多个URL quicklink.prerender(['2.html', '3.html', '4.js']);

设置滚动时预取的请求优先级

默认为低优先级(rel=prefetch或XHR)。对于高优先级(priority: true),尝试使用fetch()或回退到XHR。

**注意:**这会在options.el容器内找到的URL上运行prefetch(..., true)

quicklink.listen({priority: true});

指定允许的源的自定义列表

提供应该可预取的主机名列表。默认情况下只允许相同源。

**重要:**你还必须包括你自己的主机名!

quicklink.listen({ origins: [ // 添加自己的 'my-website.com', 'api.my-website.com', // 添加第三方 'other-website.com', 'example.com', // ... ], });

允许所有源

启用所有跨源请求。

**注意:**你可能会遇到CORBCORS问题!

quicklink.listen({ origins: true, // 或 origins: [], });

自定义忽略模式

这些过滤器在origins匹配之后运行。忽略可用于避免大文件下载或动态响应DOM属性。

// 默认启用同源限制。 // // 此示例将忽略所有对以下内容的请求: // - 所有"/api/*"路径名 // - 所有".zip"扩展名 // - 所有具有"noprefetch"属性的<a>标签 // quicklink.listen({ ignores: [ /\/api\/?/, uri => uri.includes('.zip'), (uri, elem) => elem.hasAttribute('noprefetch'), ], });

你可能还希望忽略包含URL片段的URL预取(例如index.html#top)。如果你(1)正在使用页面中的锚点标题或(2)为单页应用设置了URL片段,并希望避免为类似的URL触发预取,这可能很有用。

使用ignores可以实现如下:

quicklink.listen({ ignores: [ uri => uri.includes('#'), // 或正则表达式:/#(.+)/ // 或元素匹配:(uri, elem) => !!elem.hash ], });

通过hrefFn回调自定义要预取的URL

hrefFn方法允许动态构建要预取的URL(例如API端点),而不是预取href属性URL。

quicklink.listen({ hrefFn(element) { return element.href.replace('html', 'json'); }, });

浏览器支持

quicklink提供的预取可以视为渐进增强。跨浏览器支持如下:

  • 无需填充:Chrome、Safari ≥ 12.1、Firefox、Edge、Opera、Android Browser、Samsung Internet。
  • 使用Intersection Observer polyfill(约6KB gzip压缩/最小化):Safari ≤ 12.0、IE11
  • 使用上述填充以及Set()Array.from填充:IE9和IE10。Core.js提供了Set()Array.from()两种垫片。es6-shim等项目是你可以考虑的替代方案。

某些功能具有分层支持:

直接使用预取器

prefetch 方法可以单独导入以在其他项目中使用。

该方法包含了尊重数据节省模式和 2G 连接的逻辑。它还会根据 isPriority 值和当前浏览器的支持情况,通过 fetch()、XHR 或 link[rel=prefetch] 发出请求。

在将 quicklink 安装为依赖项后,你可以按以下方式使用它:

<script type="module"> import {prefetch} from 'quicklink'; prefetch(['1.html', '2.html']).catch(error => { // 处理自己的错误 }); </script>

演示

Glitch 演示

研究

这是我们演示WebPageTest 运行结果,通过 quicklink 的预取功能将页面加载性能提高了最多 4 秒。YouTube 上有一个预取前后对比的视频

出于演示目的,我们在 Firebase 托管上部署了 Google Blog 的一个版本。然后我们部署了另一个版本,在主页上添加了 quicklink,并对从主页导航到自动预取的文章进行了基准测试。预取版本加载得更快。

请注意:这绝不是对视口内链接预取的优缺点的全面基准测试。只是展示了这种方法可能带来的潜在改进。你自己的实际效果可能会有很大差异。

其他说明

会话拼接

跨源预取(例如 a.com/foo.html 预取 b.com/bar.html)有许多限制。其中一个限制是会话拼接。b.com 可能期望 a.com 的导航请求包含会话信息(例如临时 ID - 如 b.com/bar.html?hash=<>&timestamp=<>),这些信息用于自定义体验或记录分析信息。如果会话拼接需要 URL 中的时间戳,预取并存储在 HTTP 缓存中的内容可能与用户最终导航到的内容不同。这带来了一个挑战,因为它可能导致双重预取。

为了解决这个问题,你可以考虑通过 ping 属性(单独)传递会话信息,以便源站可以异步拼接会话。

广告相关考虑

依赖广告作为收入来源的网站不应预取广告链接,以避免无意中计算这些广告位置的点击次数,这可能导致广告点击率(CTR)虚高。

广告主要以两种方式出现在网站上:

  • 在 iframe 内: 默认情况下,大多数广告服务器在 iframe 内渲染广告。在这些情况下,除非开发人员明确传入广告 iframe 的 URL,否则 Quicklink 不会预取这些广告链接。原因是库对视口内元素的查找仅限于顶级源的元素。

  • 在 iframe 外: 当网站显示同源广告,直接显示在顶级文档中(例如,自行托管广告并直接在页面中显示)时,开发人员需要明确告诉 Quicklink 避免预取这些链接。这可以通过将广告链接的 URL 或子路径,或包含它的元素传递给自定义忽略模式列表来实现。

相关项目

  • 使用 Gatsby?你已经免费获得了大部分这些功能。它使用 Intersection Observer 预取所有在视图中的链接,并为本项目提供了重要灵感。
  • 想要更加数据驱动的方法?看看 Guess.js。它使用分析和机器学习基于用户如何浏览你的网站来预取资源。它还有 WebpackGatsby 的插件。
  • WordPress 用户现在可以从插件库中获得 quicklink 作为 WordPress 插件
  • Drupal 用户可以安装 Quicklink Drupal 模块
  • Magento 2 用户可以安装 rafaelcg-magento2-quicklinkrangerz/magento2-module-quicklink
  • 想要不那么激进的预取?instant.page 在鼠标悬停和触摸开始时预取,就在点击之前。

许可证

根据 Apache-2.0 许可证 授权。

编辑推荐精选

Vora

Vora

免费创建高清无水印Sora视频

Vora是一个免费创建高清无水印Sora视频的AI工具

Refly.AI

Refly.AI

最适合小白的AI自动化工作流平台

无需编码,轻松生成可复用、可变现的AI自动化工作流

酷表ChatExcel

酷表ChatExcel

大模型驱动的Excel数据处理工具

基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。

AI工具酷表ChatExcelAI智能客服AI营销产品使用教程
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
AIWritePaper论文写作

AIWritePaper论文写作

AI论文写作指导平台

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

AI辅助写作AI工具AI论文工具论文写作智能生成大纲数据安全AI助手热门
博思AIPPT

博思AIPPT

AI一键生成PPT,就用博思AIPPT!

博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。

AI办公办公工具AI工具博思AIPPTAI生成PPT智能排版海量精品模板AI创作热门
潮际好麦

潮际好麦

AI赋能电商视觉革命,一站式智能商拍平台

潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。

iTerms

iTerms

企业专属的AI法律顾问

iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。

SimilarWeb流量提升

SimilarWeb流量提升

稳定高效的流量提升解决方案,助力品牌曝光

稳定高效的流量提升解决方案,助力品牌曝光

Sora2视频免费生成

Sora2视频免费生成

最新版Sora2模型免费使用,一键生成无水印视频

最新版Sora2模型免费使用,一键生成无水印视频

下拉加载更多