加载时间从4.6s降到0.7s,谷歌开源quicklink

近日,Google团队在GitHub上开源了一个项目quicklink,quicklink能在空闲时预取viewport内的链接来加快后续页面的加载速度。具体的技术原理和实现过程请看下文。

工作原理

quicklink通过以下措施加快后续页面的加载速度:

  • 检测viewport中的链接,使用Intersection Observer

  • 等待浏览器空闲,使用requestIdleCallback

  • 检查用户的连接速度(使用navigator.connection.effectiveType)或者是否启用了data-saver(使用navigator.connection.saveData);

  • 预取链接(使用或XHR),可以控制请求优先级(如果支持,可以切换到fetch())。

为什么要推出quicklink?

quicklink旨在成为根据用户viewport中的链接预取内容的简易解决方案,而且要保持很小的体积(压缩后小于1KB)。

安装

npm install --save quicklink

也可以从unpkg.com/quicklink下载quicklink。

用法

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

\u0026lt;!-- Include quicklink from dist --\u0026gt;\u0026lt;script src=\u0026quot;dist/quicklink.umd.js\u0026quot;\u0026gt;\u0026lt;/script\u0026gt;\u0026lt;!-- Initialize (you can do this whenever you want) --\u0026gt;\u0026lt;script\u0026gt;quicklink();\u0026lt;/script\u0026gt;

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

\u0026lt;script\u0026gt;window.addEventListener('load', () =\u0026gt;{   quicklink();});\u0026lt;/script\u0026gt;

ES模块导入:

import quicklink from \u0026quot;quicklink/dist/quicklink.mjs\u0026quot;;quicklink();

上面的选项最适合多页面网站。单页应用程序也有几个可用的选项:

  • 在完成新路由导航后调用quicklink();
  • 针对特定的DOM元素/组件调用quicklink();
  • 使用自定义URL调用quicklink({urls:[…]})进行预取。

API

quicklink可以接受带有以下参数的可选选项对象:

  • el:包含需要预取的链接的DOM元素;

  • urls:要预取的URL数组(不是在viewport中检测到的文档或DOM元素的链接);

  • timeout:requestIdleCallback超时时间,浏览器执行预取的时间(以毫秒为单位),默认为2秒;

  • timeoutFn:用于指定超时的函数,默认为requestIdleCallback,也可以替换为networkIdleCallback等自定义函数;

  • priority:布尔值,指定预取优先级,默认为false。如果设置为true,将尝试使用fetch() API(而不是rel=prefetch);

  • origins:允许预取的URL主机名字符串数组。默认为与域名相同的origin,防止跨origin请求;

  • ignores:一个RegExp函数或数组,用于决定是否应该预取某个URL。在orign匹配之后执行。

待完成事项:

  • 检测资源的文件扩展名,并使用rel=preload进行高优先级预取;

  • 使用Priority Hints进行重要性提示。

polyfill

quicklink:

  • 可以回退到requestIdleCallback;

  • 需要支持IntersectionObserver,请参阅CanIUse。我们建议使用Polyfill.io等服务来有条件地polyfill该功能:

\u0026lt;script src=\u0026quot;https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver\u0026quot;\u0026gt;\u0026lt;/script\u0026gt;

一些示例

设置自定义的资源预取超时时间

默认为2秒(通过requestIdleCallback),在这里我们将其设置为4秒:

quicklink({  timeout: 4000});

设置包含预取URL的DOM元素

如果不设置,默认为document。

const elem = document.getElementById('carousel');quicklink({  el: elem});

设置预取URL数组

如果你想要直接提供预取URL的列表,而不是去检测viewport,可以使用URL数组。

quicklink({   urls: ['2.html','3.html', '4.js']});

设置预取的请求优先级

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

quicklink({ priority: true });

指定origin自定义列表

提供可预取的主机名列表。默认情况下只允许来自相同origin的URL。

quicklink({  origins: [    // add mine    'my-website.com',    'api.my-website.com',    // add third-parties    'other-website.com',    'example.com',    // ...  ]});

允许所有origin

启用所有跨origin请求。

quicklink({  origins: true,  // or  origins: []});

自定义Ignore模式

这些过滤器在origin匹配之后运行,对于避免下载大文件或动态响应DOM属性来说非常有用。

// Same-origin restraint is enabled by default. This example will ignore all requests to://  - all \u0026quot;/api/*\u0026quot; pathnames//  - all \u0026quot;.zip\u0026quot; extensions//  - all \u0026lt;a\u0026gt; tags with \u0026quot;noprefetch\u0026quot; attribute//quicklink({  ignores: [    /\\/api\\/?/,    uri =\u0026gt; uri.includes('.zip'),    (uri, elem) =\u0026gt; elem.hasAttribute('noprefetch')  ]});

你可能希望忽略包含URL片段的URL(例如index.html #top)。如果你在页面中使用了锚点或为单页面应用程序设置了URL片段,希望避免触发此类URL的预取, 那么这项功能非常有用。

quicklink({    ignores: [        uri =\u0026gt; uri.includes('#')        // or RegExp: /#(.+)/        // or element matching: (uri, elem) =\u0026gt; !!elem.hash    ]});

浏览器支持

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

  • 没有polyfill:Chrome、Firefox、Edge、Opera、Android Browser, Samsung Internet。

  • 使用Intersection Observer polyfill:Safari、IE11。

  • 上面的再加上Set()和Array.from polyfill:IE9和IE10。Core.js提供了Set()和Array.from()填充,也可以考虑es6-shim

提供了某些功能的分层支持:

  • Network Information API,用于检查用户的连接类型(通过navigator.connection.effectiveType),仅适用于Chrome 61+和Opera 57+。

  • 如果选择{priority: true}并且Fetch API不可用,则将使用XHR。

直接使用prefetcher

quicklink包含一个prefetcher,可以单独导入到其他项目中使用。在将quicklink作为依赖项安装好以后,可以按如下方式使用它:

\u0026lt;script type=\u0026quot;module\u0026quot;\u0026gt;import prefetch from '../src/prefetch.mjs';const urls = ['1.html', '2.html'];const promises = urls.map(url =\u0026gt; prefetch(url));Promise.all(promises);\u0026lt;/script\u0026gt;

演示

这里是一个WebPageTest演示

通过使用quicklink,将页面加载时间减少了4秒。这里是进行预取前后的比较视频

出于演示的目的,我们在Firebase上部署了一个谷歌博客,然后我们又部署了另一个版本,在主页上添加了quicklink,并测试从主页导航到文章的速度,结果预取版本的加载速度更快。

请注意:这并不是一个针对viewport内链接预取优缺点的详尽基准测试,我们只是演示了这个方法可以为我们带来的潜在改进。

英文原文:https://github.com/GoogleChromeLabs/quicklink

更多内容,请关注前端之巅。

\"\"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值