概述
最近事情繁忙,有段时间没写笔记了,就让我再摆一会吧,好了,废话不多说,开始正文!由于之前在项目里面用到了H5离线缓存策略Service Worker,但是做这个功能似乎过去了很久,最近会想起来的时候,都已经差不多忘记其中的细节了,这里再次捡起来,总起以下,方面后面能用到。
最终目标
在网页网络断掉或者服务停掉的时候,我们在当前浏览的网页上能继续使用其部分功能。而不是弹出一个掉网的页面。
效果
Service Worker的由来
W3C 组织早在 2014 年 5 月就提出过 Service Worker 这样的一个 HTML5 API ,主要用来做持久的离线缓存。service worker是浏览器的一个高级特性,本质是一个web worker,是独立于网页运行的脚本。 web worker这个api被造出来时,就是为了解放主线程。因为,浏览器中的JavaScript都是运行在单一个线程上,随着web业务变得越来越复杂,js中耗时间、耗资源的运算过程则会导致各种程度的性能问题。 而web worker由于独立于主线程,则可以将一些复杂的逻辑交由它来去做,完成后再通过postMessage的方法告诉主线程。 service worker则是web worker的升级版本,相较于后者,前者拥有了持久离线缓存的能力。总结一下,比较实用的就是可以拦截请求做离线缓存。
Service Worker的特点
- 独立于主线程、在后台运行的脚本
- 被install后就永远存在,除非被手动卸载
- 必须是https的协议才能使用。不过在本地调试时,在localhost下也是可以跑起来的。
- 可拦截请求和返回,缓存文件。sw可以通过fetch这个api,来拦截网络和处理网络请求,再配合cacheStorage来实现web页面的缓存管理以及与前端postMessage通信。
Service Worker的工作流程
下面的这张图我找到的,算是比较清晰。我们的初衷(缓存,缓存哈哈)
注意事项
由于直接自己去编写缓存Server Work程序会相当的麻烦,要考虑到工程化项目打包后的静态资源缓存,还要涉及到很多的CacheStorage的操作,实际上的离线缓存的实现要复杂的多。既然如此,我们最好是站在巨人的肩膀上,webpack提供了一个插件,能够自动生成 Service Worker 和 静态资源列表 - workbox-webpack-plugin。
使用方法
这里我拿一个成型的vue项目使用这个来举例
安装
npm install workbox-webpack-plugin --save-dev
vue.config.js配置
const path = require('path');
const WorkboxPlugin = require('workbox-webpack-plugin');
module.exports = {
chainWebpack: config => {
//使用插件
config.plugin('WorkboxPlugin').use(WorkboxPlugin.GenerateSW, [
{
clientsClaim: true,
skipWaiting: true,
maximumFileSizeToCacheInBytes: 30 * 1024 * 1024,
},
]);
},
devServer: {
open: true,
host: '0.0.0.0',
port: 8080,
https: false,
hotOnly: false,
},
};
注册 Service Worker
serviceWorker对象存在于navigator对象下,可以再主线程中调用navigator.serviceWorker.register()方法来注册servicework,register 方法接受两个参数,第一个参数表示servicework.js相对于origin的路径,第二个参数是 Serivce Worker 的配置项,可选填,其中比较重要的是 scope 属性,用来指定你想让 service worker 控制的内容的目录。 默认值为servicework.js所在的目录。这个属性所表示的路径不能在 service worker 文件的路径之上,默认是 Serivce Worker 文件所在的目录。
//App.vue
mounted() {
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/service-worker.js')
.then(registration => {
console.log('SW registered: ', registration);
})
.catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
},
好了,接下来可以使用http-server来创建一个serve,项目跑起来,然后停掉网络,或者关闭服务刷新页面可以看到,页面依然存在,不会显示网络错误。
总结
Service Worker的离线缓存在对应网页缓存中还是不错的,可以给用户带来更好的体验,站在巨人的肩膀上编程,可以试着在项目里面用起来。