service worker學(xué)習(xí)筆記

介紹

Service workers 本質(zhì)上充當(dāng)Web應(yīng)用程序與瀏覽器之間的代理服務(wù)器且叁,也可以在網(wǎng)絡(luò)可用時作為瀏覽器和網(wǎng)絡(luò)間的代理槽驶。它們旨在(除其他之外)使得能夠創(chuàng)建有效的離線體驗泊窘,攔截網(wǎng)絡(luò)請求并基于網(wǎng)絡(luò)是否可用以及更新的資源是否駐留在服務(wù)器上來采取適當(dāng)?shù)膭幼鳌K麄冞€允許訪問推送通知和后臺同步API若锁。
Service worker是一個注冊在指定源和路徑下的事件驅(qū)動worker泽台。它采用JavaScript控制關(guān)聯(lián)的頁面或者網(wǎng)站,攔截并修改訪問和資源請求访娶,細(xì)粒度地緩存資源商虐。你可以完全控制應(yīng)用在特定情形(最常見的情形是網(wǎng)絡(luò)不可用)下的表現(xiàn)。

Service worker運行在worker上下文,因此它不能訪問DOM秘车。相對于驅(qū)動應(yīng)用的主JavaScript線程典勇,它運行在其他線程中,所以不會造成阻塞叮趴。它設(shè)計為完全異步割笙,同步API(如XHR和localStorage不能在service worker中使用

出于安全考量眯亦,Service workers只能由HTTPS承載伤溉,畢竟修改網(wǎng)絡(luò)請求的能力暴露給中間人攻擊會非常危險。在Firefox瀏覽器的用戶隱私模式妻率,Service Worker不可用乱顾。

Service workers之所以優(yōu)于以前同類嘗試(如AppCache),是因為它們無法支持當(dāng)操作出錯時終止操作宫静。Service workers可以更細(xì)致地控制每一件事情走净。
Service workers大量使用Promise,因為通常它們會等待響應(yīng)后繼續(xù)孤里,并根據(jù)響應(yīng)返回一個成功或者失敗的操作伏伯。Promise非常適合這種場景。

根據(jù)官方的介紹不難看出扭粱,Service worker提供了更有效的緩存請求資源控制手段舵鳞。


基本使用

使用ServiceWorkerContainer.register()注冊service worker,這將作用于整個域內(nèi)用戶可訪問的URL琢蛤,或者其特定子集蜓堕。

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

taobaofed為什么說 SW是網(wǎng)站的大腦?舉個例子博其,如果在 www.example.com的根路徑下注冊了一個 SW套才,那么這個 SW 將可以控制所有該瀏覽器向 www.example.com 站點發(fā)起的請求。只需要監(jiān)聽 fetch 事件慕淡,你就可以任意的操縱請求背伴,可以返回從 CacheStorage 中讀的數(shù)據(jù),也可以通過 Fetch API 發(fā)起新的請求峰髓,甚至可以 new 一個 Response傻寂,返回給頁面。

直接看一個完整的sw文件示例去體會用法:

var cacheStorageKey = 'cachesName';
var cacheList = [
  // 注冊成功后要立即緩存的資源列表
]

// 當(dāng)瀏覽器解析完 SW 文件時觸發(fā) install 事件
self.addEventListener('install', function(e) {
  // install 事件中一般會將 cacheList 中要緩存的內(nèi)容通過 addAll 方法携兵,
  // 請求一遍放入 caches 中
  e.waitUntil(
    caches.open(cacheStorageKey).then(function(cache) {
      return cache.addAll(cacheList)
    })
  );
});

// 激活時觸發(fā) 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)
    // 也可以從遠(yuǎn)端拉取
    fetch(e.request.url)
    // 也可以自己造
    new Response('自己造')
    // 也可以通過吧 fetch 拿到的響應(yīng)通過 caches.put 方法放進(jìn) caches
  );
});

監(jiān)聽install事件,在解析完后寫入需要緩存的cache
監(jiān)聽activate事件徐紧,觸發(fā)時可以清理舊緩存和舊的service worker關(guān)聯(lián)的東西静檬。
監(jiān)聽fetch事件炭懊,去響應(yīng)請求,通過respondWith去任意修改對于這些請求的響應(yīng)拂檩。
示例也基本符合了MDN官方給出的使用建議侮腹。


Workbox 3

workbox被定義為 PWA 相關(guān)的工具集合,可以把它理解為 Google 官方的 PWA 框架稻励,它解決的就是用底層 API 寫 PWA 太過復(fù)雜的問題父阻,讓管理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時塞進(jìn)caches的內(nèi)容至非。workbox.routing.registerRoute去匹配請求路徑,匹配上了走相應(yīng)的請求策略糠聪,等于activate和fetch方法都合并在了一個方法里去配置,更加獨立簡介明了谐鼎。


緩存策略

  • Stale-While-Revalidate 當(dāng)請求的路由有對應(yīng)的 Cache 緩存結(jié)果就直接返回舰蟆,在返回 Cache 緩存結(jié)果的同時會在后臺發(fā)起網(wǎng)絡(luò)請求拿到請求結(jié)果并更新 Cache 緩存,如果本來就沒有 Cache 緩存的話狸棍,直接就發(fā)起網(wǎng)絡(luò)請求并返回結(jié)果身害,這對用戶來說是一種非常安全的策略,能保證用戶最快速的拿到請求的結(jié)果草戈,但是也有一定的缺點塌鸯,就是還是會有網(wǎng)絡(luò)請求占用了用戶的網(wǎng)絡(luò)帶寬
  • Cache First (Cache Falling Back to Network) 當(dāng)匹配到請求之后直接從 Cache 緩存中取得結(jié)果唐片,如果 Cache 緩存中沒有結(jié)果丙猬,那就會發(fā)起網(wǎng)絡(luò)請求,拿到網(wǎng)絡(luò)請求結(jié)果并將結(jié)果更新至 Cache 緩存费韭,并將結(jié)果返回給客戶端茧球。這種策略比較適合結(jié)果不怎么變動且對實時性要求不高的請求
  • Network First (Network Falling Back to Cache) 請求路由是被匹配的星持,就采用網(wǎng)絡(luò)優(yōu)先的策略抢埋,也就是優(yōu)先嘗試拿到網(wǎng)絡(luò)請求的返回結(jié)果,如果拿到網(wǎng)絡(luò)請求的結(jié)果督暂,就將結(jié)果返回給客戶端并且寫入 Cache 緩存揪垄,如果網(wǎng)絡(luò)請求失敗,那最后被緩存的 Cache 緩存結(jié)果就會被返回到客戶端逻翁,這種策略一般適用于返回結(jié)果不太固定或?qū)崟r性有要求的請求饥努,為網(wǎng)絡(luò)請求失敗進(jìn)行兜底
  • Network Only 直接強(qiáng)制使用正常的網(wǎng)絡(luò)請求卢未,并將結(jié)果返回給客戶端肪凛,這種策略比較適合對實時性要求非常高的請求堰汉。
  • Cache Only 直接使用 Cache 緩存的結(jié)果,并將結(jié)果返回給客戶端伟墙,這種策略比較適合一上線就不會變的靜態(tài)資源請求翘鸭。

總結(jié)心得

雖然MDN上指出IE、Safari目前并不支持戳葵,參考淘寶 PC 首頁的 Service Worker 上線已經(jīng)有好長一段時間了就乓,其實是可以考慮逐漸引入使用的。且因為通過官方提供的底層API去寫可能太過復(fù)雜拱烁,直接使用workbox是一個不錯的策略生蚁!


參考

Workbox 3:Service Worker 可以如此簡單
Service_Worker_API from MDN
workbox緩存策略

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市戏自,隨后出現(xiàn)的幾起案子邦投,更是在濱河造成了極大的恐慌,老刑警劉巖擅笔,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件志衣,死亡現(xiàn)場離奇詭異,居然都是意外死亡猛们,警方通過查閱死者的電腦和手機(jī)念脯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弯淘,“玉大人绿店,你說我怎么就攤上這事÷龋” “怎么了假勿?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長态鳖。 經(jīng)常有香客問我废登,道長,這世上最難降的妖魔是什么郁惜? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任堡距,我火速辦了婚禮,結(jié)果婚禮上兆蕉,老公的妹妹穿的比我還像新娘羽戒。我一直安慰自己,他們只是感情好虎韵,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布易稠。 她就那樣靜靜地躺著,像睡著了一般包蓝。 火紅的嫁衣襯著肌膚如雪驶社。 梳的紋絲不亂的頭發(fā)上企量,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機(jī)與錄音亡电,去河邊找鬼届巩。 笑死,一個胖子當(dāng)著我的面吹牛份乒,可吹牛的內(nèi)容都是我干的恕汇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼或辖,長吁一口氣:“原來是場噩夢啊……” “哼瘾英!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起颂暇,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤缺谴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后耳鸯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓣赂,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年片拍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妓肢。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡捌省,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碉钠,到底是詐尸還是另有隱情纲缓,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布喊废,位于F島的核電站祝高,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏污筷。R本人自食惡果不足惜工闺,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓣蛀。 院中可真熱鬧陆蟆,春花似錦、人聲如沸惋增。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诈皿。三九已至林束,卻和暖如春像棘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壶冒。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工缕题, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人依痊。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓避除,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胸嘁。 傳聞我的和親對象是個殘疾皇子瓶摆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345