---
author: 青云工作室
bottom_meta: true
categories:
  - web
comments: true
cover: false
date: '2022-11-18 14:40:54'
description: serviceworkers首屏优化
headimg: 'https://npm.elemecdn.com/chenyfan-os@0.0.0-r17/main.jpg'
indent: true
mathjax: false
pin: false
tags:
  - 前端
  - web
  - 博客
  - sw
title: serviceworkers首屏优化
toc: true
top_meta: true
abbrlink: 52948
---
{% note info::本片文章默认你已经会使用sw来加速网站了 %}
## 前言
前阵子，我开始用cyf大佬的sw加速方案，前前后后我使用了三个不同作者所开发的sw加速，但是因cyf的代码过于难以了解（我菜），而去使用了yfun大佬的代码，以便网页在前端被更新

## 为什么要首屏优化
在使用cyf大佬的方案是我发现了cyf的首屏优化方案
> 事实上，ServiceWorker最显著的缺点是要在第一次加载网页安装后，刷新一次才能激活。即访客第一次访问是不受sw控制的。换句话说，访客首屏不受加速，其加载速度与你的服务器有直接联系 ~~[虽然安装完成后就起飞了,但安装前就是屑]~~。

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

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

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

### 方案1（by cyfan）
{% folding cyan::打开复制源码 %}

```
<!-- sw前端竞速 -->
<script>
(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);
    }
})()
</script>
```

{% endfolding %}

### 方案2（by yfun）
{% folding cyan::打开复制源码 %}

```
<!-- sw前端竞速 -->
<script>
(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);
    }
})()
</script>
```

{% endfolding %}

### 注意事项
{% note warning::我们尽可能将打断代码提到`<head>` 以确保不被其他资源堵塞，对于hexo来说打开主题的head.ejs，在`<head>`标签靠前的位置中加入，否则可能达不到理想的加速效果 %}