service worker 是獨立於當前頁面的一段運行在瀏覽器後臺進程裏的腳本,它是一個獨特的Web Worker。html
日常瀏覽器窗口中跑的頁面運行的是主JavaScript線程,DOM和window全局變量都是能夠訪問的。Service Worker是走的另外的線程,能夠理解爲在瀏覽器背後默默運行的一個線程,或者說是獨立於當前頁面的一段運行在瀏覽器後臺進程裏的腳本。它脫離瀏覽器窗體,異步地運行在一個徹底獨立的上下文環境,不會對主線程形成阻塞。在service worker中,window以及DOM都是不能訪問的,但可使用PostMessage跟主進程進行通訊。前端
1.離線緩存(重點)依賴於cacheAPIvue
2.消息推送(重點)依賴於Google的推送服務,國內使用意義不大webpack
3.後臺數據同步git
4.響應來自其它源的資源請求github
5.集中接收計算成本高的數據更新,好比地理位置和陀螺儀信息,這樣多個頁面就能夠利用同一組數據web
6.在客戶端進行CoffeeScript,LESS,CJS/AMD等模塊編譯和依賴管理(用於開發目的,一些在線編譯網站)redis
7.後臺服務鉤子(基於推送)chrome
8.自定義模板用於特定URL模式編程
9.性能加強,好比預取用戶可能須要的資源,好比相冊中的後面數張圖片
1.瀏覽器兼容性:不支持IE,可是因爲是另一個線程,不影響在IE上使用。
使用ServiceWorker cache polyfill讓舊版本瀏覽器支持 ServiceWorker cache API。
[瀏覽器兼容性](ww1.sinaimg.cn/large/007iU…)
2.https: Service Worker必須是https協議的,但本地環境下http://localhost或者http://127.0.0.1也能夠的。
經過service worker能夠劫持鏈接,僞造和過濾響應,爲了不這些問題,只能在HTTPS的網頁上註冊service workers,防止加載service worker的時候不被壞人篡改。
Github Pages是HTTPS的,能夠經過Github作一些嘗試
3.service worker運行在它們本身的徹底獨立異步的全局上下文中,也就是說它們有本身的容器。
4.service worker沒有直接操做DOM的權限,可是能夠經過postMessage方法來與Web頁面通訊,讓頁面操做DOM。
5.service worker是一個可編程的網絡代理,容許開發者控制頁面上處理的網絡請求。
6.瀏覽器可能隨時回收service worker,在不被使用的時候,它會本身終止,而當它再次被用到的時候,會被從新激活。
7.service worker的生命週期是由事件驅動的而不是經過Client。
service worker擁有一個徹底獨立於Web頁面的生命週期
Service Worker生命週期的反應:installing → installed → activating → activated 'install'用來緩存文件,'activate'用來緩存更新
[Service Worker生命週期](pic.superbed.cn/item/5c8b19…)
註冊service worker,在網頁上生效
安裝成功,激活 或者 安裝失敗(下次加載會嘗試從新安裝)
激活後,在sw的做用域下做用全部的頁面,首次控制sw不會生效,下次加載頁面纔會生效
sw做用頁面後,處理fetch(網絡請求)和message(頁面消息)事件 或者 被終止(節省內存)。
一、chrome://serviceworker-internals
[serviceworker-internals](ww1.sinaimg.cn/large/007i4…)
二、網頁中Application
[Application1](ww1.sinaimg.cn/large/007iU…)
[Application2](ww1.sinaimg.cn/large/007i4…)
HTML 裏面:
引進sw-demo-cache.js
webapck中的使用:
獲取文件目錄 引入第三個模塊glob,遞歸獲取打包後的文件目錄。導出目錄 經過webpack的DefinePlugin插件,導出上步獲取的目錄
web和service worker的通訊 經過postMessage實現web和service worker間的通訊
Service Worker的業界生態
Service Worker 主要在PWA中擔任離線緩存應用技術的角色。
Webpack的offline-plugin, offline-plugin 能夠把咱們的多頁面應用進行緩存,即便這些html文件時獨立的。它做爲一個webpack插件使用,爲咱們自動生成sw.js文件。
workbox:是sw-precache和sw-toolbox的繼任者。它是一組內容庫和工具,用於生成 Service Worker、預緩存、路由以及運行時緩存。另外,Workbox還附帶模塊,可輕鬆地將後臺同步和Google analytics集成到 Service Worker。通俗來看,它能幫助開發人員下降Service Worker的使用成本,但目前沒辦法高效解決大型站點多團隊多應用協做的問題。主要用於SPA。主要應用有淘寶最近分享的workbox3.0
lavas:是一套基於 Vue 的 PWA 解決方案,可以幫助開發者快速搭建 PWA 應用,解決接入 PWA 的各類問題,簡單來看lavas = vue + pwa。它適用於新應用的開發,對於老應用使用PWA有必定成本,並且一樣目前也沒辦法高效解決大型站點多團隊多應用協做的問題。主要用於SPA。
開發人員接入只需兩步:
在PWA管理平臺填寫相關配置,這些配置會存到redis集羣。
在頁面引入一小段js代碼,這段代碼在頁面加載時執行,先向配置平臺發出sw-reg.js請求,拉取配置,而後在頁面註冊sw。
爲了提升sw可用性,管理平臺設計時將sw與配置解耦。實際頁面在零基礎狀況下應用PWA時會經歷三次頁面請求才能成功使用:
第一次頁面請求註冊sw並控制頁面;
第二次頁面請求拉取配置經過postmessage形式傳給sw並存儲在IndexedDB;
第三次頁面請求時sw會攔截頁面上全部http請求,根據配置執行相應的處理策略。
從框圖中能夠看到,sw將緩存存儲在CacheStorage,數據和配置存儲在IndexedDB。整個流程包括服務端和客戶端都有報警監控,錯誤上報到cat。
整個平臺設計與業務基本徹底解耦,要求業務在不接入PWA狀況下也能正常使用,平臺只是幫助業務在頁面請求加載各個環節加強體驗。
應用場景很普遍,一些應用到sw的站點:
百度、谷歌、騰訊、163網易、微博(m.weibo.cn/)、淘寶 PC 首頁......
基本應用場景在手機端使用比較多,Web端也不少。
手機端應用得比較好的是mobile.twitter.com,在手機上的體驗跟原生很接近。
Service Worker在咱們的項目中的應用:
咱們的設想是在離線的狀況下,用戶可以無感知的進行操做,而且在操做以後能把
操做對應的上傳到服務器上……
爲了達成這個目標,咱們須要使用SW在瀏覽器中作好緩存策略的選擇:
對於某些固定不變的靜態資源,咱們習慣在Service Worker初次安裝的install事件中將其緩存,但資源過大或者網絡不佳都會形成資源並未所有下載成功而致使Service Worker安裝被中斷,只有等下次用戶在打開相應頁面。這裏能夠將靜態資源按優先級分爲兩類,一類是重要資源,一類是非重要資源,將重要資源放到安裝等待隊列中,非重要資源放到獨立的隊列中,這樣只須要重要資源所有都加載成功就能夠成功安裝Service Worker了,能夠提升Service Worker安裝成功率。
對於在install中發現沒有緩存,頁面又依賴但又不常常變化的資源,能夠在頁面打開或發生用戶交互時觸發fetch而後使用fetch api再去網絡拉取,將返回正常的response緩存起來以便下次使用。
在fetch事件中,僅去匹配資源,若匹配失敗,表現出來的就是前端頁面對於該 資源加載失敗。這裏容錯性比較差,適合頁面資源都是靜態資源的,且不能使用不影響安裝的資源預緩存。
在fetch事件中,僅將request從新抽出用fetch去網絡加載並返回給前端頁面。適用於資源大可能是動態資源、實時性要求高的場景。
簡單的資源緩存中使用的就是緩存優先策略,先去緩存匹配,匹配失敗折回網絡,這算是最經常使用、容錯性能好的一種策略。
在fetch事件中先去網絡fetch,當出現服務器故障或者網絡不良時,折回本地緩存,目的是爲了展現最新的數據,對實時性要求比較高但又可以帶來良好體驗的應用,好比天氣類型應用。
在fetch事件中同時發起本地緩存匹配及網絡請求,誰先返回使用誰的,該方案適用於對性能要求比較高的站點,縮短了緩存優先策略中有可能緩存中沒有資源再折回網絡的時間消耗。
a. 首先保證跨域的資源來自安全的https地址;
b. 保證跨域資源服務器的response中Access-Control-Allow-Origin中包含當前的頁面所在域或者爲*;
c. 對於前端頁面中的跨域資源的url能夠附帶「cors=1」參數,以便Service Worker在攔截以後能夠判斷出是跨域請求從而從新進行組裝cors請求。
淘寶分享的WorkBox3.0實踐中推薦使用的方案:
HTML,若是你想讓頁面離線能夠訪問,使用 NetworkFirst,若是不須要離線訪問,使用 NetworkOnly,其餘策略均不建議對 HTML 使用。
CSS 和 JS,狀況比較複雜,由於通常站點的 CSS,JS 都在 CDN 上,SW 並無辦法判斷從 CDN 上請求下來的資源是否正確(HTTP 200),若是緩存了失敗的結果,問題就大了。這種我建議使用 Stale-While-Revalidate 策略,既保證了頁面速度,即使失敗,用戶刷新一下就更新了。
若是你的 CSS,JS 與站點在同一個域下,而且文件名中帶了 Hash 版本號,那能夠直接使用 Cache First 策略。
圖片建議使用 Cache First,並設置必定的失效事件,請求一次就不會再變更了。
上面這些只是普適性的策略,見仁見智。還有,要牢記,對於不在同一域下的任何資源,絕對不能使用 Cache only 和 Cache first。