Progressive Web Applications take advantage of new technologies to bring the best of mobile sites and native applications to users. They're reliable, fast, and engaging.html
用戶首次訪問service worker控制的網站或頁面時,service worker會馬上被下載。
ServiceWorker(web worker 的一種)接口
Cache:表示對request/response對象的存儲,一個域能夠有多個 Cache 對象. 你將在你的代碼中處理和更新緩存 . 在 Cache 除非顯示地更新緩存, 不然緩存將不會被更新; 緩存數據不會過時, 除非刪除它
Cache.match(request, options)返回一個Promise,查找cache中匹配的request
Cache.match(request, options)匹配一個數組對象中的request
Cache.add(request)發送請求並將請求放入cache中,
Cache.put(request, response)將request和response都添加到cache中
Cache.delete(request, options) 才cache中查找鄉音的值,並刪除返回一個promise,resoleve爲true,若是找不到返回false
Cache,keys(request, options)返回一個promise,resolve爲全部的cache鍵值vue
CacheStorage: 對Cache對象的存儲,提供命名緩存的主目錄,sw能夠經過訪問並維護名字字符串到Cache對象的映射
caches.open(cacheName).then(names){};//打開一個cache對象ios
Client: 表示sw client的做用域。git
sw.js中的self:這個關鍵字表示的是一個service worker 的執行上下文的一個全局屬性(ServiceWorkerGlobalScope),相似於window對象,不過這個self是做用於service worker的全局做用域中。github
if(navigator.serviceWorker){ navigator.serviceWorder.register('sw.js') .then(registration => { console.log(`registered event at scope:${registration.scope}`); }) .cache(err => { throw err; }) }
self.addEventListener('install', function(event) { // Perform install steps });
緩存文件web
const cacheVersion = 'v1'; const cacheList = [ '/', 'index.html', 'logo.png', 'manifest.json', '/dist/build.js' ]; self.addEventListener('install', function(event) { event.waitUntil( caches.open(cacheVersion).then(function(cache) { return cache.addAll([cacheList]); }) ); });
event.waitUntil()參數必須爲promise,它能夠延長一個事件的做用時間,由於咱們在打開緩存或者更新的時候頗有可能會有延遲,而event.waitUntil()能夠防止事件終端。另外它會監聽全部的異步promise,一旦有一個reject那麼該次event即是失敗的,也就是說sw啓動失敗。固然若是有些文件比較大很差緩存的話別讓它返回就行了:json
cache.addAll([cachelist1]); return cache.addAll([cachelist2]);
緩存捕獲,當發起請求的時候將request和response緩存下來(緩存一開始定義的緩存列表)。axios
self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request) .then(response => { if(response){ return reponse; } return fetch(event.request); }) ) })
這是個比較簡單的格式,event.respondWith(r),包含請求響應代碼,能夠設置一個參數r,r是一個promise,resolve以後是一個response對象。整段代碼意思就是當請求一個文件時,若是緩存中已經有了,那麼就直接返回緩存結果,不然發起請求。數組
手動緩存promise
self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { if(response){ return response; } //fetch請求的request、response都定義爲stream對象,因此只能讀一次這裏須要clone一個新的 let requestObj = event.request.clone(); return fetch(requestObj) .then(response => { //檢測是否成功 if(!response || response.status !== 200 || response.type !== 'basic') { return response; } //若是請求成功,第一要去渲染,第二要緩存 //cache.put()也使用stream,因此這裏也須要複製一份 let responseObj = response.clone(); caches.open(cacheVersion) .then(cache => { cache.put(event.request, responseObj); }); return response; }) }) ) })
當可讀流讀取一次以後可能已經讀到stream結尾或者stream已經close了,這裏request和response都實現了clone接口來複制一份,因此在須要二次使用stream的時候就須要用副原本實現了。
self.addEventListener('activate', evnet => { event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.filter(cachename => { if(cachename == cacheVersion){ return caches.delete(cachename); } }) ).then(() => { return self.clients.claim() }) }) ) })
咱們檢查以前保存的sw緩存,還要注意一點就是Promise.all()中不能有undefined,因此咱們對於相同的版本要過濾,於是不使用map,避免返回undefined。
經過調用 self.clients.claim() 取得頁面的控制權, 這樣以後打開頁面都會使用版本更新的緩存。
當你更新了你的sw文件,並修改了cacheVersion以後,刷新瀏覽器,期待的變化並無發生,由於雖然你改變了緩存版本,可是此時舊的sw還在控制整個應用,新的sw並無生效。這時就須要更新一下sw,有如下方法
navigator.serviceWorker.register('/sw.js').then(reg => { // sometime later… reg.update(); });
self.addEventListener('install', event => { self.skipWaiting(); event.waitUntil( // caching ); });
直接點擊update便可。
注意,咱們更新了某些文件的時候也要同時更新sw中的緩存版本(cacheVersion)
這個文件主要是配置添加到桌面的一些基本信息,好比圖標啓動頁等。詳細能夠看這個https://developer.mozilla.org/zh-CN/docs/Web/Manifest
或者拉取這個項目https://github.com/Stevenzwzhai/PWA-demo
項目地址https://github.com/Stevenzwzhai/zhihu-daily
演示地址https://stevenzwzhai.github.io/zhihu-daily/