ServiceWorker 优化项目缓存命中率

2,035 阅读4分钟

前言

本文是基于项目优化接入Service Worker(后续简写为sw)工具来讲述workbox-webpack-plugin插件的接入使用,对于Service Worker的基础内容不会详细讲解,如想了解,可参考:developer.mozilla.org/zh-CN/docs/… developers.google.com/web/fundame…

基本概念

Service Worker 概念

说明

  1. Service Worker 是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门。
  2. 它本质上充当 Web 应用程序、浏览器与网络(可用时)之间的代理服务器。这个 API 旨在创建有效的离线体验,它会拦截网络请求并根据网络是否可用采取来适当的动作、更新来自服务器的的资源。它还提供入口以推送通知和访问后台同步 API。

【注意】:Service worker运行在worker上下文,因此它不能访问DOM。相对于驱动应用的主JavaScript线程,它运行在其他线程中,所以不会造成阻塞。它设计为完全异步,同步API(如XHRlocalStorage (en-US))不能在service worker中使用

先决条件

1、浏览器支持

2、HTTPS

  • 在开发过程中,可以通过 localhost 使用 Service Worker,但如果要在网站上部署 Service Worker,则需要在服务器上设置 HTTPS。

  • 使用服务工作线程,您可以劫持连接、编撰以及过滤响应。 这是一个很强大的工具。 您可能会善意地使用这些功能,但中间人可会将其用于不良目的。 为避免这种情况,可仅在通过 HTTPS 提供的页面上注册 Service Worker,如此我们便知道浏览器接收的 Service Worker 在整个网络传输过程中都没有被篡改。

生命周期

image.png

  1. 当使用方法  navigator.serviceWorker.register注册一个新的ServiceWorker时,浏览器会下载JS脚本,解析脚本。这时ServiceWorker处于 installing状态。如果安装成功,则进入 installed状态,否则会进入 redundant状态。
  2. ServiceWorker成功安装后便进入installed状态。至此Service完成了安装过程,等待进入激活过程
  3. ServiceWoker安装成功后进入activating状态。
  4. activated这时ServiceWorker可以控制页面了,可以监听功能事件了,如fetch,push事件。默认情况下ServiceWorker只能控制在其激活成功后才加载完成的页面
  5. redundant状态是ServiceWorker的终态

workbox-webpack-plugin 概念

workbox-webpack-plugin 介绍

Workbox 提供了两个webpack插件:一个为您生成完整的 Service Worker,另一个生成要预缓存的资产列表,并注入到 Service Worker 文件中。

插件在workbox-webpack-plugin模块中实现为两个类,named GenerateSWInjectManifest. 具体介绍可以参考 developers SW

workbox-webpack-plugin 接入

1、安装

npm i --save  workbox-webpack-plugin
2、在webpack中使用 GenerateSW

image.png 【注意】:

  1. swDest 必须与index.html处于同一目录下,因为生成的servicework文件只能去匹配该目录下的子目录文件;
  2. clientsClaim Service Worker 被激活后使其立即获得页面控制权
  3. skipWaiting 强制等待中的 Service Worker 被激活 
  4. runtimeCaching属性配置:
    1. urlPattern 匹配的正则规则
    2. handler属性是以何种方式缓存
      1. 'CacheFirst' :本地缓存优先

      2. 'CacheOnly' :只支持缓存

      3. 'NetworkFirst':网络优先

      4. 'NetworkOnly' :支持网络

      5. 'StaleWhileRevalidate':网络与缓存并行

5.buildConfig.VERSION 是一个时间戳,代表sw生成的版本,后续业务代码中获取sw文件也是通过VERSION来获取

3.注册service worker

image.png

【注意】:

  1. 由于正式环境访问的是gaems开头的域名url地址,但是接口访问的是deo开头的域名,但serviceworker必须在同域下进行缓存操作,所以需要保证同域相同
  2. 由于serviceworker是持久缓存,开发过程如果使用,会出现代码/接口数据发生更改,但是页面仍然获取到的是之前已经缓存的数据,所以为了避免该事件产生,只有在NODE_ENV === ‘production’时才会进行注册
  3. 如果url含有sw参数,就代表不需要使用serviceworker,便于调试
  4. 如果servicerworker存在,但是不触发的情况,需要将浏览器中存在的serviceworker注销
  5. 一旦注册成功以后,会将  window.SERVICE_WORKER  设置为true,标志着注册成功

4.接入成功的效果

image.png

image.png 可以看到访问的静态资源和其他资源都是优先从serviceworker 获取

sw.js js实现

前面的实现是通过workbox封装好的webpack-plugin自动生成的,那么它的js是如何实现的呢?

image.png

image.png

参考文件

Workbox 3:Service Worker 可以如此简单:fed.taobao.org/blog/taofed…

Service Worker API: developer.mozilla.org/zh-CN/docs/…

Service Worker 介绍developers.google.com/web/fundame…