背景
这几天领导找我,说我们的H5页面内置了很多链接,这些链接的打开的速度有点慢,你有什么办法可以优化一下么?或者有什么好的方案可以拿出来聊聊,我心想,这提升速度的方案无非就那么几种,我要是优化不好,就目前这就业形势,怕是要把我优化了
其实按照惯性,本质来说打开速度慢作为前端的我们无非从以下三点优化
- 「优化资源,请求并行」
- 「优化代码,提升渲染速度」
- 「告诉后端接口响应快点」
这三种不论哪一种,提升的速度只能说是一般,毕竟我们已经做过相关的优化了,再做有点产出和人力不匹配了,除了这些,一些链接不属于我们内部的,这种有没有办法呢?可不可以从另一个方面来考虑问题?
由于是H5页面打开之后,所有的链接都是内嵌的,内嵌的话我们找到这个链接,提前加载是不是就可以了,正好前几天看到一个库,quicklink,是chrome浏览器团队出的,它可以加快打开链接的速度
https://github.com/GoogleChromeLabs/quicklink
真的这么神奇么?
我们来看一下这个库的基本原理,它的主要作用是通过空闲的时间来提前获取视口内的链接进行预渲染或者预加载,使后面我们打开的链接能够快速
它到底是怎么做到的
检测视口元素
首先,它要知道进入视口的元素有哪些,从而获取进入视口元素的链接,所以第一步先看哪些元素进入视口了
Intersection Observer,这个是JS中的一个API,主要用来检测目标元素是否到达了指定位置,这个API用处非常大,之前我们检测的时候会不断去看某个元素的位置信息和高度信息进行对比,判断,来做一些我们想做的事情,有了这个API,你可以很方便的进行比如图片懒加载,上拉加载下拉刷新的操作,某个元素到某个位置的时候执行什么操作,和之前一直使用scroll事件的监听简化了很多
比如要检测红色方块是否处于屏幕内外,可使用下列代码
代码语言:javascript复制const io = new IntersectionObserver((o) => console.log(o), {})
io.observe(document.getElementsByTagName('div')[0])
如果元素在屏幕内出现或者消失,都会打印o这个数据,具体的可查看MDN,然后拿到视图内的元素查找元素对应的链接,链接便获取到了
浏览器空闲时间
requestIdleCallback这个api虽然是一个实验中的功能,但是目前已经能够在各大主流浏览器中使用
它的主要作用是在浏览器空闲的时候执行一些函数,用法是在这个函数中传入一个待执行的函数,比如
代码语言:javascript复制window.requestIdleCallback(() => console.log('我将在浏览器空闲的时候调用'))
检测连接状态
对于一些使用慢网的用户,我们需要提前检测用户当前网络状态,网络不好的情况下不采用预加载的方式
代码语言:javascript复制navigator.connection.effectiveType
// 4g
如果用户想要减少流量的使用,可用下面的api进行检测,返回一个布尔值
代码语言:javascript复制navigator.connection.saveData
// boolean
预加载
预加载的方式有以下几种
link prefetch
最简单的一种就是在页面添加link标签
代码语言:javascript复制<link rel="prefetch" href="https://baidu.com">
添加完link标签之后,当你看页面请求的时候,你会发现,它会在浏览器空闲时间去请求预加载的链接
如果动态去添加link标签可以么?测试一下
代码语言:javascript复制const linkPrefetch = document.createElement('link');
linkPrefetch.setAttribute('rel','prefetch');
linkPrefetch.setAttribute('href','https://www.baidu.com');
document.head.appendChild(linkPrefetch)
同样也能达到上述效果
或者使用XMLHttpRequest对象进行相应的请求,再或者使用fetch
预渲染
上图是预渲染和没有预渲染的结果对比,很明显预渲染的页面打开速度要更快,使用Speculation Rules API可以灵活的配置需要预渲染的页面
代码语言:javascript复制<script type="speculationrules">
{
"prerender": [
{
"source": "list",
"urls": ["next.html", "next2.html"]
}
]
}
</script>
动态添加预渲染也是OK的,跟link类似,但是前提我们要判断当前浏览器是否支持Speculation Rules API
代码语言:javascript复制if (HTMLScriptElement.supports &&
HTMLScriptElement.supports('speculationrules')) {
const specScript = document.createElement('script');
specScript.type = 'speculationrules';
specRules = {
prerender: [
{
source: 'list',
urls: ['/next.html'],
},
],
};
specScript.textContent = JSON.stringify(specRules);
console.log('added speculation rules to: next.html');
document.body.append(specScript);
}
总结
要想使用quicklink这个库,它的原理我们上面基本上都说明了,使用方面也比较简单,对整个项目的影响几乎没有
代码语言:javascript复制<script src="https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.3.0/quicklink.umd.js"></script>
<script>
window.addEventListener('load', () => {
quicklink.prefetch(["https://baidu.com"])
});
只需要做如上配置你就能够预加载你想要的链接,当然你也可以不用自己手动配置,直接使用如下代码即可,它就会根据一系列的判断,将预加载在合适的时机进行加载
代码语言:javascript复制window.addEventListener('load', () => {
quicklink.listen();
});
不论要不要加预加载或者预渲染,前提都是要保证不影响用户资源,导致过度渲染,要做到确保用户点击这个链接的可能性很高的时候再预渲染,感兴趣的话可以关注公众号【FE情报局】
调研完成之后,我们在项目中使用了Quicklink,转化率提高了50%,页面转换速度和打开速度提高了好几倍,领导对我刮目相看,升职加薪指日可待