今天看啥  ›  专栏  ›  yanziNote

Workbox :Service Worker 初尝试

yanziNote  · 掘金  ·  · 2019-09-28 16:06
阅读 15

Workbox :Service Worker 初尝试

Service Worker

我们的应用程序的主进程主要负责渲染dom,执行交互请求,而Service Worker 是浏览器在后台独立于网页运行的,它重新在后台起了一个进程,它和应用的主进程互不影响,可以同时执行。 sw可以拦截和处理网络请求,包括通过程序来管理缓存中的响应。在使用 service-worker 前,我们必须要先在主进程中注册它,然后才能在 service-worker 进程中编写逻辑。

//index.js. 注册SW
if ("serviceWorker" in navigator) {
    // Use the window load event to keep the page load performant
    window.addEventListener("load", () => {
      navigator.serviceWorker.register("/service-worker.js").then(registration=>{
        console.log("register succces...")
      }, err=>{
        console.log("register error...",err)
      });
    });
  }

复制代码

demo

我们在根路径下注册了一个 SW,那SW 就可以拦截对应服务下的所有请求。只需要监听 fetch 事件,你就可以任意的操纵请求,可以返回从 CacheStorage 中读的数据,也可以通过 Fetch API 发起新的请求,甚至可以 new 一个 Response,返回给页面。

service-worker
//service-worker.js  简单输出一些文本
console.log('Hello from service-worker.js');

var cacheStorageKey = 'cachesName';
var cacheList = [
   // 注册成功后要立即缓存的资源列表
    "/test.css",
    "/index.js",
    {
      url: "/index.html",
      revision: "383676" //-- revision 可以通过工具插件workbox-webpack-plugin维护
    }
]

// 当浏览器解析完 SW 文件时触发 install 事件  安装SW
self.addEventListener('install', function(e) {
  // install 事件中一般会将 cacheList 中要换存的内容通过 addAll 方法,请求一遍放入 caches 中
  e.waitUntil(
    caches.open(cacheStorageKey).then(function(cache) {
      return cache.addAll(cacheList)
    })
  );
});

// 激活时触发 activate 事件
self.addEventListener('activate', function(e) {
  // active 事件中通常做一些过期资源释放的工作,匹配到就从 caches 中删除
  var cacheDeletePromises = caches.keys().then(cacheNames => {
    return Promise.all(cacheNames.map(name => {
      if (name !== cacheStorageKey) {
        return caches.delete(name);
      } else {
        return Promise.resolve();
      }
    }));
  });

  e.waitUntil(
    Promise.all([cacheDeletePromises])
  );
});

// 缓存和返回请求
self.addEventListener('fetch', function(e) {
  // 在此编写缓存策略
  e.respondWith(
    // 可以通过匹配缓存中的资源返回
    caches.match(e.request)
    // 也可以从远端拉取
    fetch(e.request.url)
    // 也可以自己造
    new Response('hell0')
    // 也可以通过吧 fetch 拿到的响应通过 caches.put 方法放进 caches
  );
});


复制代码

test

Workbox

workbox 用于支持离线web apps的js库, 是Google 根据SW的最佳实践推出的官方框架,封装了SW底层的API来监听SW的安装,激活,fetch事件以及缓存等相关逻辑处理,使用起来更简单方便。

  • 预缓存
  • 运行时缓存np
  • 策略(Strategies)
  • 请求路由
  • 后台同步
  • 便捷的调试
  • 相比于 sw-precache和 sw-toolbox 具有更大的灵活性和更完备的功能

Workbox 的主要功能是它的路由和缓存策略模块。侦听网页的请求,并根据策略如何缓存和响应请求。这两个功能的具体实现对应于它们的workerbox的workbox.routing ,workbox.strategies 和workbox.precaching。 通过 workbox.routing 模块提供的路由控制和 workbox.strategies 模快提供的缓存策略控制帮助你做动态缓存。通过workbox.precaching 模块来处理 Service Worker 静态资源的预缓存。

缓存策略

利用 workbox.precaching 模块来处理 Service Worker 静态资源的预缓存。

  //  precache (预缓存) 静态文件 通常项目中的 sw.js 源文件都是通过这样预留一个空数组的方式来预缓存内容列表的
  workbox.precaching.precacheAndRoute([
    // 注册成功后要立即缓存的资源列表
    "/test.css",
    "/index.js",
    {
      url: "/index.html",
      revision: "383676"    //-- revision 可以通过工具插件workbox-webpack-plugin维护
    }
  ]);

复制代码

路由请求

workbox.routing有3种方式来拦截匹配到的请求

  • string
  • 正则
  • 回调函数
// string
workbox.routing.registerRoute(
  '/logo.png',
  handler
);

// RegExp
workbox.routing.registerRoute(
  new RegExp('\\.js$'),
  jsHandler
 );
 

// Callback Function
const matchFunction = ({url, event}) => {
  // Return true if the route should match
  return false;
};

workbox.routing.registerRoute(
  matchFunction,
  handler
);



复制代码

上述中的处理函数有两种方式

  • 使用workbox.strategies.
  • 提供一个Promise的回调函数

然而,利用 workbox.routing 模块提供的路由控制和 workbox.strategies 模快提供的缓存策略控制帮助你做动态缓存。

缓存策略

Stale While Revalidate

这种策略当请求的路由有对应的 Cache 缓存结果就直接返回,在返回 Cache 缓存结果的同时会在后台发起网络请求拿到请求结果并更新 Cache 缓存,如果本来就没有 Cache 缓存的话,直接就发起网络请求并返回结果。

workbox.routing.registerRoute(
    match, // 匹配的路由
    workbox.strategies.staleWhileRevalidate()
);
复制代码
Network First

这种策略就是当请求路由是被匹配的,就采用网络优先的策略,也就是优先尝试拿到网络请求的返回结果,如果拿到网络请求的结果,就将结果返回给客户端并且写入 Cache 缓存,如果网络请求失败,那最后被缓存的 Cache 缓存结果就会被返回到客户端,这种策略一般适用于返回结果不太固定或对实时性有要求的请求,为网络请求失败进行兜底。

Cache First

这个策略的意思就是当匹配到请求之后直接从 Cache 缓存中取得结果,如果 Cache 缓存中没有结果,那就会发起网络请求,拿到网络请求结果并将结果更新至 Cache 缓存,并将结果返回给客户端。这种策略比较适合结果不怎么变动且对实时性要求不高的请求。

之前的疑问,如果网络请求一直失败的情况, 是和 Stale While Revalidate的动作一样的 ,是发请求,成功之后然后更新缓存,如果第一次也是失败的,缓存中无对应结果,同样也是是发请求,成功之后然后更新缓存。

Network Only

比较直接的策略,直接强制使用正常的网络请求,并将结果返回给客户端,这种策略比较适合对实时性要求非常高的请求。可以像如下方式使用 Network Only 策略:

Cache Only

这个策略也比较直接,直接使用 Cache 缓存的结果,并将结果返回给客户端,这种策略比较适合一上线就不会变的静态资源请求。可以像如下方式使用 Cache Only 策略

tips

  • 查看启动的SW

    • chrome://inspect/#service-workers查看启动的sw
  • https sw 只工作在安全模式下

    • 本地的local和http 模式下sw都注册不成功。
  • Web App Manifest Generator这个工具可以帮助生成 manifest

  • 策略

    • 静态资源图片等使用 Cache First
    • CSS 和 JS, 使用 Stale-While-Revalidate 策略,既保证了页面速度,即便失败,用户刷新一下就更新了
    • 不建议使用 Cache only 和 Cache first

参考

Workbox 官方文档 Workbox 3.0

代码实例

GitHub




原文地址:访问原文地址
快照地址: 访问文章快照