quicklink 为你的页面实现秒开
quicklink是什么
是一个通过资源预加载来提升后续方案的轻量级工具库。旨在提升浏览器中,用户访问后续页面的加载速度。
当我们提到性能优化,往往想到的是用户访问当前的这个页面,例如如何压缩资源、减少http请求、精简js代码等来提升页面的访问速度。而quicklink换用了另外一种思路,帮你预加载接下来你最可能访问的资源,这样之后访问这个页面就会感到非常顺畅。
quicklink工作原理
- 检测可视区的链接(a标签、script标签)
- 等待浏览器空闲
- 检查用户是否处于慢速链接
- 获取可视区的url
quicklink 安装使用方法参照文档
1.安装
npm install --save quicklink
2.快速上手,必须在页面链接加载完之后调用
<script src="https://unpkg.com/quicklink@1.0.0/dist/quicklink.umd.js"></script>
<script>
window.addEventListener('load', function () {
quicklink();
});
或者es6导入模块
import quicklink from '/dist/quicklink.umd.js';
quicklink();
以上配置适用于多页网站,单页应用可以搭配router使用:
- 进入新路由地址后,调用 quicklink()
- 针对特定 DOM 元素/组件调用 quicklink()
- 调用 quicklink({urls:[…]}),传入自定义 URL 集合进行预获取
API
quicklink 接受带有以下参数的 option 对象(可选)
- el:指定需要预获取的 DOM 元素视区
- urls:预获取的静态 URL 数组(若此配置非空,则不会检测视区中 document 或 DOM 元素的链接),不在可视区也会预加载
- timeout:为 requestIdleCallback 设置的超时整数。 浏览器必须在此之前进行预获取(以毫秒为单位), 默认取 2 秒。
- timeoutFn:指定超时处理函数。 默认为 requestIdleCallback。
- priority:布尔值,指定 fetch 的优先级。 默认为 false。 若配置为 true 将会尝试使用 fetch() API(而非 rel = prefetch)
window.addEventListener('load', function () {
var box=document.getElementById('box')
quicklink({
timeout: 4000,
el:box,
urls:['/open/formalOpenConfirm11'],
priority:true
});
});
浏览器支持
浏览器支持
quicklink 提供的预获取是渐进增强的(progressive enhancement), 跨浏览器支持如下:
- 不使用 polyfills 情况:Chrome,Firefox,Edge,Opera,Android Browser,Samsung Internet 支持
- 使用 Intersection Observer polyfill(gzipped/minified 后大约 6KB):Safari,IE9+ 支持
某些功能支持分层实现。即如果 {priority:true} 和 fetch 不可用,则将使用 XHR。
源码解读
缓存策略
quicklink默认的是实现缓存那些在可视区的连接,同时也提供了一些api来手动缓存那些资源。
那最重要的问题,就是如何知道那些连接是在可视区的。
-
一种方式是监听scroll,判断每个链接在视口中的坐标。劣势就很明显了,scroll触发很频繁,也会触发浏览器的重排和重绘
-
quicklink使用的是IntersectionObserver,提供的是一种异步的方式监听元素是否进入可视区或指定祖先元素。
在quicklink中的实现方式
var box=document.getElementById('box')
var container=document.getElementById('container')
var observer = new IntersectionObserver((changes)=>{
for (const change of changes){
console.log('time'+change.intersectionRatio); //可视区发生改变的时间戳
// console.log(change.rootBounds); //可视区
}
},{
root:container //设置可视区范围,只要在这个可视区就会触发回跳函数,container一般是一个div盒子,不传默认的是整个视图的区域
});
observer.observe(container);
observer.observe(box);
// observer.unobserve(box);// 移除一个监听,移除之后,target元素的可视区域变化,将不再触发前面的回调函数
// observer.disconnect(); // 停止所有的监听
// console.log(observer);
还有一个,为了不影响主线程,将兼容逻辑放在了requestIdelCallback,这样就只有在浏览器空闲的时候,才会执行里面的回跳方法
var i=0;
window.requestIdelCallback(dd())
//会在浏览器空闲时期依次调用函数, 这就可以让开发者在主事件循环中执行后台或低优先级的任务
function dd() {
if(i<100){
i++;
console.log(i);
window.requestIdelCallback(dd())
}
}