最近闲来无事,把网站升级了,更加像原生APP
记录下升级过程,免得以后忘了
PWA是什么?可以去网上搜一下,but中文文章少一点
用Google 封装的 好的 workbox 来升级
注册Service Worker#
在html页面注册 SW
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations()
.then(regs => {
for (let reg of regs) {
// 注销掉不是当前作用域的所有的 Service Worker
if (reg.scope !== 'http://localhost:8000/') {
reg.unregister()
}
}
// 注销掉污染 Service Worker 之后再重新注册自己作用域的 Service Worker
window.addEventListener('load', () => {
navigator.serviceWorker.register('./sw.js').then(function (e) { console.log("支持sw:", e.scope) })
})
})
}
</script>
|
生成SW.js文件#
google cdn#
1
2
|
importScripts(" 'https://storage.googleapis.com/workbox-cdn/releases/6.1.1/workbox-sw.js'
");
|
国内建议不使用Google
jsdelivr cdn#
1
|
importScripts("https://fastly.jsdelivr.net/npm/[email protected]/build/workbox-sw.min.js");
|
SW.js 编写#
配置相关#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
workbox.setConfig(
{
// 是否开启debug
debug: false
}
);
let cacheSuffixVersion = '-220806'; // 缓存版本号
const maxEntries = 100; // 最大条目数
workbox.core.setCacheNameDetails({
prefix: 'zsan', // 前缀
suffix: cacheSuffixVersion, // 后缀
});
//检测是否安装成功
if (workbox) {
console.log("Yay! Workbox is loaded 🎉")
} else {
console.log("Boo! Workbox didn't load 😬")
}
|
预缓存文件#
1
2
3
4
5
6
7
8
|
let cacheFiles = [
{
url: "/index.html",
revision: cacheSuffixVersion
}
];
workbox.precaching.precacheAndRoute(cacheFiles);
|
workbox策略#
cdn策略#
对于一些cdn的使用,使用CacheFirst 缓存优先策略,此策略将首先检查缓存中是否有响应,如果有响应,则使用该策略。如果请求不在缓存中,则将使用网络,并将任何有效响应添加到缓存中,然后再传递给浏览器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
workbox.routing.registerRoute(
new RegExp('^https://fastly\\.jsdelivr\\.net'),
new workbox.strategies.CacheFirst({
cacheName: 'static-immutable' + cacheSuffixVersion,
fetchOptions: {
mode: 'cors',
credentials: 'omit',
},
plugins: [
new workbox.expiration.ExpirationPlugin({
maxAgeSeconds: 30 * 24 * 60 * 60,
purgeOnQuotaError: true,
}),
],
})
);
|
字体文件#
对于字体文件,基本上确定好就不会改动了,这里使用StaleWhileRevalidate,此策略将对网络请求使用缓存来响应(如果有),并在后台更新缓存。如果未缓存,它将等待网络响应并使用它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
workbox.routing.registerRoute(
// 匹配 woff 字体
new RegExp('.*.woff'),
new workbox.strategies.StaleWhileRevalidate({
// cache storage 名称和版本号
cacheName: 'font-cache' + cacheSuffixVersion,
plugins: [
// 使用 expiration 插件实现缓存条目数目和时间控制
new workbox.expiration.ExpirationPlugin({
// 最大保存项目
maxEntries,
// 缓存 30 天
maxAgeSeconds: 30 * 24 * 60 * 60,
}),
// 使用 cacheableResponse 插件缓存状态码为 0 的请求
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
],
})
);
|
API资源#
API数据的请求使用NetworkFirst 策略,此策略将尝试首先从网络获得响应。如果收到响应,它将把它传递给浏览器,并将其保存到缓存中。如果网络请求失败,将使用最后一个缓存的响应。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
workbox.routing.registerRoute(
// 匹配 leancloudapi.xsbb.ml
new RegExp('^https://(?:blog\\.zsan\\.ml)'),
new workbox.strategies.NetworkFirst({
// cache storage 名称和版本号
cacheName: 'blog-api-cache' + cacheSuffixVersion,
fetchOptions: {
mode: 'cors',
credentials: 'omit',
},
networkTimeoutSeconds: 3,
})
);
|
Google-Analytics#
官方有Google Analytics 离线统计插件,但是英文的,相关资料也少,折腾了好一阵子
1、简单点,一句代码就行,注意用这个时候,head里的代码需要是官方获取的最新的
1
|
workbox.googleAnalytics.initialize()
|
2、带离线统计
需要去Google analytics 添加自定义指标和自定义维度
1
2
3
4
5
6
7
8
9
|
workbox.googleAnalytics.initialize({
parameterOverrides: {
cd1: 'offline',
},
hitFilter: (params) => {
const queueTimeInSeconds = Math.round(params.get('qt') / 1000);
params.set('cm1', queueTimeInSeconds);
},
});
|
其他后缀匹配#
保证体验良好
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
workbox.routing.registerRoute(
new RegExp('.*.(?:png|jpg|jpeg|svg|gif|webp|ico)'),
new workbox.strategies.StaleWhileRevalidate()
);
workbox.routing.registerRoute(
new RegExp('.*.(css|js)'),
new workbox.strategies.StaleWhileRevalidate()
);
// 默认
workbox.routing.setDefaultHandler(
new workbox.strategies.NetworkFirst({
networkTimeoutSeconds: 3,
})
);
|
改造完成,尽情享用🎉
参考资料#
初识 Service Worker —— 使用 Workbox 快速开发 Service Worker - 宝硕博客
PWA来了,你准备好了么? - PWA学习手册
HOME · PWA 应用实战
Service worker overview - Chrome Developers