service worker学习笔记

介绍

Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。
Service worker是一个注册在指定源和路径下的事件驱动worker。它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。

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

出于安全考量,Service workers只能由HTTPS承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险。在Firefox浏览器的用户隐私模式,Service Worker不可用。

Service workers之所以优于以前同类尝试(如AppCache),是因为它们无法支持当操作出错时终止操作。Service workers可以更细致地控制每一件事情。
Service workers大量使用Promise,因为通常它们会等待响应后继续,并根据响应返回一个成功或者失败的操作。Promise非常适合这种场景。

根据官方的介绍不难看出,Service worker提供了更有效的缓存请求资源控制手段。


基本使用

使用ServiceWorkerContainer.register()注册service worker,这将作用于整个域内用户可访问的URL,或者其特定子集

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
}

taobaofed为什么说 SW是网站的大脑?举个例子,如果在 www.example.com的根路径下注册了一个 SW,那么这个 SW 将可以控制所有该浏览器向 www.example.com 站点发起的请求。只需要监听 fetch 事件,你就可以任意的操纵请求,可以返回从 CacheStorage 中读的数据,也可以通过 Fetch API 发起新的请求,甚至可以 new 一个 Response,返回给页面。

直接看一个完整的sw文件示例去体会用法:

var cacheStorageKey = 'cachesName';
var cacheList = [
  // 注册成功后要立即缓存的资源列表
]

// 当浏览器解析完 SW 文件时触发 install 事件
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('自己造')
    // 也可以通过吧 fetch 拿到的响应通过 caches.put 方法放进 caches
  );
});

监听install事件,在解析完后写入需要缓存的cache
监听activate事件,触发时可以清理旧缓存和旧的service worker关联的东西。
监听fetch事件,去响应请求,通过respondWith去任意修改对于这些请求的响应。
示例也基本符合了MDN官方给出的使用建议。


Workbox 3

workbox被定义为 PWA 相关的工具集合,可以把它理解为 Google 官方的 PWA 框架,它解决的就是用底层 API 写 PWA 太过复杂的问题,让管理service worker更加简单。

直接来看taobaofed给出的案例

// 首先引入 Workbox 框架
importScripts('[https://storage.googleapis.com/workbox-cdn/releases/3.3.0/workbox-sw.js](https://storage.googleapis.com/workbox-cdn/releases/3.3.0/workbox-sw.js)');
workbox.precaching([
 // 注册成功后要立即缓存的资源列表
]);

// html的缓存策略
workbox.routing.registerRoute(
 new RegExp(''.*\.html'),
 workbox.strategies.networkFirst()
);

workbox.routing.registerRoute(
 new RegExp('.*\.(?:js|css)'),
 workbox.strategies.cacheFirst()
);

workbox.routing.registerRoute(
 new RegExp('https://your\.cdn\.com/'),
 workbox.strategies.staleWhileRevalidate()
);

workbox.routing.registerRoute(
 new RegExp('[https://your\.img\.cdn\.com/](https://your/.img/.cdn/.com/)'),
 workbox.strategies.cacheFirst({
 cacheName: 'example:img'
 })
);

对比原先就比较清晰明了。workbox.precaching即install时塞进caches的内容。workbox.routing.registerRoute去匹配请求路径,匹配上了走相应的请求策略,等于activate和fetch方法都合并在了一个方法里去配置,更加独立简介明了。


缓存策略

  • Stale-While-Revalidate 当请求的路由有对应的 Cache 缓存结果就直接返回,在返回 Cache 缓存结果的同时会在后台发起网络请求拿到请求结果并更新 Cache 缓存,如果本来就没有 Cache 缓存的话,直接就发起网络请求并返回结果,这对用户来说是一种非常安全的策略,能保证用户最快速的拿到请求的结果,但是也有一定的缺点,就是还是会有网络请求占用了用户的网络带宽
  • Cache First (Cache Falling Back to Network) 当匹配到请求之后直接从 Cache 缓存中取得结果,如果 Cache 缓存中没有结果,那就会发起网络请求,拿到网络请求结果并将结果更新至 Cache 缓存,并将结果返回给客户端。这种策略比较适合结果不怎么变动且对实时性要求不高的请求
  • Network First (Network Falling Back to Cache) 请求路由是被匹配的,就采用网络优先的策略,也就是优先尝试拿到网络请求的返回结果,如果拿到网络请求的结果,就将结果返回给客户端并且写入 Cache 缓存,如果网络请求失败,那最后被缓存的 Cache 缓存结果就会被返回到客户端,这种策略一般适用于返回结果不太固定或对实时性有要求的请求,为网络请求失败进行兜底
  • Network Only 直接强制使用正常的网络请求,并将结果返回给客户端,这种策略比较适合对实时性要求非常高的请求
  • Cache Only 直接使用 Cache 缓存的结果,并将结果返回给客户端,这种策略比较适合一上线就不会变的静态资源请求

总结心得

虽然MDN上指出IE、Safari目前并不支持,参考淘宝 PC 首页的 Service Worker 上线已经有好长一段时间了,其实是可以考虑逐渐引入使用的。且因为通过官方提供的底层API去写可能太过复杂,直接使用workbox是一个不错的策略!


参考

Workbox 3:Service Worker 可以如此简单
Service_Worker_API from MDN
workbox缓存策略

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343