浅谈 service worker

浅谈 service worker

service Worker 简介

service worker 是浏览器在后台独立于网页运行的脚本, 它打开了通向不需要网页或用户交互的功能的大门。

service worker 简介

  • 基于 web worker: 一个独立于 JavaScript 主线程的独立线程,在里面执行需要消耗大量资源的操作不会阻塞主线程
  • 在 web worker 的基础上增加了离线缓存的能力
  • 本质上充当 Web 应用程序(服务器)与浏览器之间的代理服务器,可以拦截全站的请求,并作出相应的请求。
  • 创建有效的离线体验(将一些不常更新的内容缓存在浏览器,提高访问体验)
  • 由事件驱动的, 具有生命周期
  • 可以访问 cache 和 indexDB
  • 支持推送
  • 可以让开发者自己控制管理缓存的内容以及版本

service worker 可以拦截当前网站所有的请求,进行判断,如果需要向服务器发送请求的就转给服务器,如果可以使用缓存的就使用缓存,大大提高浏览器的体验。
在客户端离线的状态下,可以将静态资源进行缓存,从而减少白屏时间,加快页面响应速度。

service worker 使用

注册SW => 安装SW => 激活SW => 空闲 => (缓存和返回请求/终止)

通过在页面中对其进行注册来启动安装。这将告诉浏览器 service Worker JavaScript 文件的位置。

1
2
3
4
5
6
7
8
9
10
11
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js', { scope: './' }).then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}

可以使用 chrome inspect 来检查 service Worker 是否已启用。
也可以 F12 -> Application -> Service Workers 查看

使用 service worker 注意事项

  • service worker 运行在 worker 上下文, 不能不能访问DOM
  • service worker 完全异步,同步 API (如 xhr 和 localstorage) 不能在其中使用
  • 出于安全考虑,service worker 只能在 https 和 localhost 环境下使用
  • service worker 其生命周期与页面无关

service worker 在 vue 项目中的实际应用

在 vue 项目中使用库 register-service-worker

1
2
3
4
yarn add register-service-worker

// main.js
import './register-service-worker'

在项目的根目录下会有一个 registerServiceWorker.js 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
},
registered() {
console.log('Service worker has been registered.')
},
cached() {
console.log('Content has been cached for offline use.')
},
updatefound() {
console.log('New content is downloading.')
},
updated() {
console.log('New content is available; please refresh.')
},
offline() {
console.log(
'No internet connection found. App is running in offline mode.'
)
},
error(error) {
console.error('Error during service worker registration:', error)
}
})
}

默认的功能有:

  • 所有构建文件的预缓存
  • 离线加载应用程序的能力
  • 在应用程序中使用 service worker 中的注册事件

service worker 用法

  1. service worker 线程发送消息到 web Application
1
2
3
4
...
updated(registration) {
document.dispatchEvent(new CustomEvent('methodName', { detail: registration }))
}
  1. web Application 监听线程消息
1
2
3
4
5
6
7
8
9
document.addEventListener('methodName', this.appUpdateUI, { once: true })

...
appUpdateUI(e) {
// 获取 registration
this.registration = registration
console.log(e.detail)
}
...
  1. web Application 层通过 postMessage 发送消息到 service worker 线程中
1
this.registration.waiting.postMessage({ type: 'SKIP_WAITING' })

参考

service worker 用法详解
service worker 是什么
service worker 在 vue 中的应用
一文了解 service worker