serviceworkers首屏优化

Note

本片文章默认你已经会使用 sw 来加速网站了

前言

前阵子，我开始用 cyf 大佬的 sw 加速方案，前前后后我使用了三个不同作者所开发的 sw 加速，但是因 cyf 的代码过于难以了解（我菜），而去使用了 yfun 大佬的代码，以便网页在前端被更新

为什么要首屏优化

在使用 cyf 大佬的方案是我发现了 cyf 的首屏优化方案

事实上，ServiceWorker 最显著的缺点是要在第一次加载网页安装后，刷新一次才能激活。即访客第一次访问是不受 sw 控制的。换句话说，访客首屏不受加速，其加载速度与你的服务器有直接联系 [虽然安装完成后就起飞了，但安装前就是屑]。

更加令人抓狂的是，在首屏加载时，静态资源会被直接获取，并且不缓存，而 sw 激活后又会强制第二次获取，拉跨速度。不过我们可以尽可能弱化这一劣势。我们可以用 js 打断所有的请求，以确保首屏只加载一个 html 和一个 sw.js，其余资源都不会加载，降低首屏加载延迟。

所以我尝试使用了 cyf 大佬的首屏优化，而且有一个帅气的 sw 安装页面谁不爱呢

我前后使用了两种首屏优化样式这里都分享出来

方案 1（by cyfan）

Copy


(async () => {//使用匿名函数确保body已载入
/*
QYBlogHelper_Set 存储在LocalStorage中,用于指示sw安装状态
0 或不存在 未安装
1 已打断
2 已安装
3 已激活,并且已缓存必要的文件(此处未写出,无需理会)
*/
if ('serviceWorker' in navigator) { //如果支持sw
if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 1) {
setTimeout(async () => {
console.log('检测到您的浏览器没有安装QYBlogHelper，开始注册')
window.stop()
window.localStorage.setItem('QYBlogHelper_Set', 1)
const replacehtml = await fetch('https://npm.elemecdn.com/chenyfan-blog@1.0.13/public/notice.html')
document.body.innerHTML = await replacehtml.text()
$('#info').innerText = '尝试安装QYBlogHelper...';
}, 0);
}
const $ = document.querySelector.bind(document);//语法糖
navigator.serviceWorker.register(`/sw.js?time=${new Date().getTime()}`)//随机数,强制更新
.then(async () => {
if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 2) {
setTimeout(() => {
$('#info').innerText = '安装成功,稍等片刻...';
}, 0);
setTimeout(() => {
window.localStorage.setItem('QYBlogHelper_Set', 2)
console.log('准备跳转')
window.location.reload()//刷新,以载入sw
}, 500)//安装后等待500ms使其激活
}
})
.catch(err => console.error(`QYBlogHelperError:${err}`))
} else {
setTimeout(() => {
$('#info').innerText = '很抱歉,我们已不再支持您的浏览器.';
}, 0);
}
})()


方案 2（by yfun）

Copy


(async () => {//使用匿名函数确保body已载入
/*
QYBlogHelper_Set 存储在LocalStorage中,用于指示sw安装状态
0 或不存在 未安装
1 已打断
2 已安装
3 已激活,并且已缓存必要的文件(此处未写出,无需理会)
*/
if ('serviceWorker' in navigator) { //如果支持sw
if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 1) {
setTimeout(async () => {
console.log('检测到您的浏览器没有安装QYBlogHelper，开始注册')
window.stop()
window.localStorage.setItem('QYBlogHelper_Set', 1)
const replacehtml = await fetch('https://npm.elemecdn.com/qycdn@0.9.13/html/swinstall.html')
document.body.innerHTML = await replacehtml.text()
}, 0);
}
const $ = document.querySelector.bind(document);//语法糖
navigator.serviceWorker.register(`/sw.js?time=${new Date().getTime()}`)//随机数,强制更新
.then(async () => {
if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 2) {
setTimeout(() => {
window.localStorage.setItem('QYBlogHelper_Set', 2)
console.log('准备跳转')
window.location.reload()//刷新,以载入sw
}, 500)//安装后等待500ms使其激活
}
})
.catch(err => console.error(`QYBlogHelperError:${err}`))
} else {
setTimeout(() => {
console.log('很抱歉,我们已不再支持您的浏览器');
}, 0);
}
})()


注意事项

Warning

我们尽可能将打断代码提到 以确保不被其他资源堵塞，对于 hexo 来说打开主题的 head.ejs，在 标签靠前的位置中加入，否则可能达不到理想的加速效果