slideOptions: transition: slide --- # 建構 PWA - Service Worker --- ### 什麼是 Service Worker ---- - Service Worker 是一種 JS 的 Web Worker ,他是一隻獨立運行於瀏覽器頁面執行緒之外的一隻 JS 檔案,可以攔截網路請求,存取快取資源,並且能傳送訊息。 - 然後呢~Service Worker 大量的使用到 promise ,所以還沒搞懂的朋友們,你可能會看不懂這東西在搞什麼鬼QQ - 因為 Service Worker 可以攔截你的網路請求,並且改變 response ,所以只能在 localhost 或是 https上使用。 --- ### 生命週期 - Registration,要使用 Service Worker 之前必須先註冊一隻js檔案,這個動作其實是告訴瀏覽器,你這隻檔案的位置在哪 - Installation,當註冊了一個 Service Worker 之後,瀏覽器會在這個檔案還沒被安裝,或是跟原本的檔案有一點不一樣的時候,試圖去安裝 - Activation,當一個 Service Worker 安裝之後,就會進到這個階段,不過要是有任何的頁面還被前一個 Service Worker 控制的情況下,那新的 Service Worker 就會進入等待,直到沒有任何頁面被前一個控制。 --- ### 動動手 ---- #### 環境需求 ---- - 瀏覽器要有支援,[看這裡](https://caniuse.com/#search=ServiceWorker) - locahost 或是 https上 --- #### 建立專案 ---- `mkdir demo-pwa && cd demo-pwa` `touch index.html index.js sw.js` `專案底下存兩張圖` ---- #### 寫code ---- index.js ```js= if ('serviceWorker' in navigator) { navigator.serviceWorker.register('./sw.js') .then(reg => console.log('註冊啦~SW registered!')) .catch(err => console.log('Error!', err)); } ``` ---- sw.js 處理 install 事件 ```js= var fileToCache = [ "要放進快取的檔案", "例如./index.js", "例如圖片檔" ] const cacheName = 'demo-pwa-static' //命名一個快取 self.addEventListener('install', event => { console.log('installing…'); event.waitUntil( // 打開這個名稱的cacheStroage,沒有的話就開一個空的cacheStroage caches.open('demo-pwa-static').then(cache=>{ //fileToCache裡的路徑指向的檔案都加進快取 return cache.addAll(fileToCache) }) ) }); ``` ---- 處理 activate 事件 ```js= self.addEventListener('activate', event => { console.log('now ready to handle fetches!'); event.waitUntil( // 取得這個 application 下的所有 cacheStorage 名稱 caches.keys().then(function(cacheNames) { console.log(cacheNames); var promiseArr = cacheNames.map(function(item) { if (item !== cacheName) { // Delete that cached file return caches.delete(item); } }) return Promise.all(promiseArr); }) ); }); ``` ---- 處理 fetch 事件 這個事件會攔截 request,並且回應 request ```js= self.addEventListener('fetch', event => { console.log('now fetch!'); console.log(event.request); event.respondWith( //當有重複的請求時,就直接拿cache裡的response當回應,沒有的話就送出請求,並且把回應存到cache裡 caches.match(event.request).then(function (response) { return response || fetch(event.request).then(res => // 存 caches 之前,要先打開 caches.open(dataCacheName) caches.open(dataCacheName).then(function(cache) { // cache.put(key, value) // 下一次 caches.match 會對應到 event.request cache.put(event.request, res.clone()); return res; }) ); }) ); }); ``` --- ### 參考 - [Introduction to Service Worker](https://developers.google.com/web/ilt/pwa/introduction-to-service-worker) - [30 天 Progressive Web App 學習筆記 系列](https://ithelp.ithome.com.tw/users/20071512/ironman/1222)