淺談PWA
3.PWA怎樣實現
上面所說PWA可實現Web App 新增至主屏、可實現離線快取,在斷網或弱網狀態下依然可以使用一些離線功能,不影響Web App體驗以及可實現使用者在不開啟瀏覽器情況下實現類似於原生App離線訊息推送功能。
那麼對於這些實現,PWA依賴於什麼?
主要依賴於manifest.json和service worker(在專案中可寫為一個名為SW.js的檔案並引入專案)
manifest.json以一個json格式的檔案被引入專案,它主要用來實現PWA頁面的新增至主屏、定義App啟動時的URL(因為PWA App本質上還是一個Web)等。
4.Service Worker
Service Worker是Chrome團隊提出的一個Web API,旨在給Web應用程式提供 高階的可持續的 後臺處理能力。相比於曾經的Web Worker這種脫離主執行緒之外的快取解決方法,Service Worker是持久的。因為web worker是臨時的,每次做的事情的結果還不能被持久存下來,如果下次有同樣的複雜操作,還得費時間的重新來一遍。
Service Workers 就像介於伺服器和網頁之間的攔截器,能夠攔截進出的HTTP 請求,從而完全控制你的網站。
最主要的特點
- 在頁面中註冊並安裝成功後,運行於瀏覽器後臺,不受頁面重新整理的影響,可以監聽和截攔作用域範圍內所有頁面的 HTTP 請求。
- 網站必須使用 HTTPS。除了使用本地開發環境除錯時(如域名使用 localhost)
- 運行於瀏覽器後臺,可以控制開啟的作用域範圍下所有的頁面請求
- 單獨的作用域範圍,單獨的執行環境和執行執行緒
- 不能操作頁面 DOM。但可以通過事件機制來處理
- 事件驅動型服務執行緒
4.1 Service Worker的使用
-
由於 Service Worker 要求 HTTPS 的環境,我們通常可以藉助於 github page 進行學習除錯。當然一般瀏覽器允許除錯 Service Worker 的時候 host 為
localhost
或者127.0.0.1
也是 ok 的。 -
Service Worker 的快取機制是依賴Cache API 實現的
-
依賴HTML5 fetch API
-
依賴Promise 實現
4.1.1 註冊
要安裝 Service Worker, 我們需要通過在 js 主執行緒(常規的頁面裡的 js )註冊 Service Worker 來啟動安裝,這個過程將會通知瀏覽器我們的 Service Worker 執行緒的 javaScript 檔案在什麼地方。
if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker.register('/sw.js', {scope: '/'}) .then(function (registration) { // 註冊成功 console.log('ServiceWorker registration successful with scope: ', registration.scope); }) .catch(function (err) { // 註冊失敗:( console.log('ServiceWorker registration failed: ', err); }); }); }複製程式碼
-
這段程式碼首先是要判斷 Service Worker API 的可用情況,支援的話咱們才繼續談實現,否則免談了。
-
如果支援的話,在頁面
onload
的時候註冊位於/sw.js
的 Service Worker。 -
每次頁面載入成功後,就會呼叫
register()
方法,瀏覽器將會判斷 Service Worker 執行緒是否已註冊並做出相應的處理。 -
register 方法的 scope 引數是可選的,用於指定你想讓 Service Worker 控制的內容的子目錄。本 demo 中服務工作執行緒檔案位於根網域, 這意味著服務工作執行緒的作用域將是整個來源。
關於
register
方法的 scope 引數,需要說明一下:Service Worker 執行緒將接收 scope 指定網域目錄上所有事項的 fetch 事件,如果我們的 Service Worker 的 javaScript 檔案在/a/b/sw.js
, 不傳 scope 值的情況下, scope 的值就是/a/b
。scope 的值的意義在於,如果 scope 的值為
/a/b
, 那麼 Service Worker 執行緒只能捕獲到 path 為/a/b
開頭的(/a/b/page1
,/a/b/page2
,...)頁面的 fetch 事件。通過 scope 的意義我們也能看出 Service Worker 不是服務單個頁面的,所以在 Service Worker 的 js 邏輯中全域性變數需要慎用。 -
then()
函式鏈式呼叫我們的 promise,當 promise resolve 的時候,裡面的程式碼就會執行。 -
最後面我們鏈了一個
catch()
函式,當 promise rejected 才會執行。
程式碼執行完成之後,我們這就註冊了一個 Service Worker,它工作在 worker context,所以沒有訪問 DOM 的許可權。在正常的頁面之外執行 Service Worker 的程式碼來控制它們的載入。
4.1.2 安裝
在你的 Service Worker 註冊成功之後呢,我們的瀏覽器中已經有了一個屬於你自己 web App 的 worker context 啦, 在此時,瀏覽器就會馬不停蹄的嘗試為你的站點裡面的頁面安裝並激活它,並且在這裡可以把靜態資源的快取給辦了。
install 事件我們會繫結在 Service Worker 檔案中,在 Service Worker 安裝成功後,install 事件被觸發。
install 事件一般是被用來填充你的瀏覽器的離線快取能力。為了達成這個目的,我們使用了 Service Worker 新的標誌性的儲存 cache API — 一個 Service Worker 上的全域性物件,它使我們可以儲存網路響應發來的資源,並且根據它們的請求來生成key。這個 API 和瀏覽器的標準的快取工作原理很相似,但是是隻對應你的站點的域的。它會一直持久存在,直到你告訴它不再儲存,你擁有全部的控制權。