Service Workers (PWA 初體驗)

在前端越來越重的這個時代,頁面加載速度成爲了一個重要的指標。對於這個問題,業界也有一些解決方案。

  1. 瀏覽器緩存、協議緩存、強緩存
  2. 懶加載(首屏)
  3. CDN 多域名突破下載併發限制。

其實在兩年前內部就對這塊內容做過調研了。appCache方案?PWA方案?但是最後都沒選擇
之前看代碼,發現是 localstroage 存代碼,如果有就拿 localstroage 去用。省去了這一部分加載的時間。
上個同事離職了。當時的調研結果我也忘了。只能再開始新一輪的調研,我選擇的是 PWA 方案。(如果說是網速拖慢了加載速度,那麼我的網頁可以離線訪問不就速度起飛了?)
網上的資料很少。我希望我可以寫一篇幫助下一個想使用 PWA 方案的人。

Service Workers

Service worker是一個註冊在指定源和路徑下的事件驅動worker

Service worker運行在worker上下文,因此它不能訪問DOM。不同於主線程,它運行在其他線程中,所以不會造成主線程阻塞。它設計爲完全異步,同步API(如XHR和localStorage)不能在service worker中使用

Service workers 本質上充當Web應用程序(服務端)瀏覽器(客戶端)之間的代理服務器
可以提供有效有效的離線體驗,攔截網絡請求。還可以推送通知。

Service Workers 需要注意的地方

  1. 需要支持 HTTPS 訪問你的頁面。出於安全原因,Service Workers 要求必須在 HTTPS 下才能運行。(其實好多API都需要HTTPS的支持)
  2. 資源路徑爲根目錄的絕對路徑。最大作用域 (scope),爲資源路徑。
    https://www.lilnong.top/static/js/sw-20190621.js的最大作用路徑爲/static/js/
  3. 爲了便於本地開發,localhost 也被瀏覽器認爲是安全源。
  4. 在已經支持 serivce workers 的瀏覽器的版本中,很多特性沒有默認開啓。如果你發現示例代碼在當前版本的瀏覽器中怎麼樣都無法正常運行,你可能需要開啓一下瀏覽器的相關配置:
    Firefox Nightly: 訪問 about:config 並設置 dom.serviceWorkers.enabled 的值爲 true; 重啓瀏覽器;
    Chrome Canary: 訪問 chrome://flags 並開啓 experimental-web-platform-features; 重啓瀏覽器 (注意:有些特性在Chrome中沒有默認開放支持);
    Opera: 訪問 opera://flags 並開啓 ServiceWorker 的支持; 重啓瀏覽器。

service worker 聲明週期

  1. 下載

    1. 首次訪問service worker控制的網站或頁面時,service worker會立刻被下載。
    2. 至少每24小時它會被下載一次。
  2. 安裝

    1. 首次下載會嘗試安裝,
    2. 下載的文件是新的,嘗試進行安裝
  3. 激活

    1. 安裝成功後它會被激活
    2. 如果現有service worker已啓用,新版本會在後檯安裝,但不會被激活,這個時序稱爲worker in waiting
    3. 直到所有已加載的頁面不再使用舊的service worker纔會激活新的service worker。新的service worker會被激活(成爲active worker)。

我們頁面引入sw.js內容爲a。當我們修改爲b
這時候ab都是已經安裝完畢的,但是a是當前正在用的。b需要等沒有頁面在用a,纔會進入激活狀態。
clipboard.png

Cache

Cache 爲緩存的 Request/Response 對象對提供存儲機制。
當前我們作爲 ServiceWorker 生命週期的一部分。儘管它被定義在 service worker 的標準中, 但是它不必一定要配合 service worker 使用。也暴露在 window 作用域下的。

  1. Cache.add(request)
    request 是一個字符串類型的 URL。如cache.add('https://www.lilnong.top/static/css/normalize-8.0.0.css')
    功能上等於調用 fetch(), 然後使用 Cache.put()response 添加到 cache 中。
  2. Cache.addAll(requests)
    功能同上,只不過入參爲字符串數組
  3. Cache.match(request, options)
    返回一個 Promise 對象,resolve 的結果是跟 Cache 對象匹配已經緩存的請求。
    requres 同上,是要匹配的 URL
    options 如下

    1. ignoreSearch: 設置是否忽略url中的query。該選項默認爲 false
    2. ignoreMethod: true匹配時就不會驗證 Request 對象的 http 方法 (通常只允許是 GETHEAD 。) 該參數默認值爲 false。
    3. ignoreVary: 爲 true 時匹配不進行 VARY 部分的匹配。例如,如果一個URL匹配,此時無論Response對象是否包含VARY頭部,都會認爲是成功匹配。該參數默認爲 false。
    4. cacheName: 一個 DOMString ,代表一個具體的要被搜索的緩存。注意該選項被 Cache.match()方法忽略。
  4. Cache.matchAll(request, options)
    同上,返回一個Promise 對象,resolve的結果是跟Cache對象匹配的所有請求組成的數組
  5. Cache.put(request, response)
    人爲的,爲一個URL設置response
  6. Cache.delete(request, options)
    搜索條目。如果找到,則刪除該Cache 條目,並且返回一個resolvetruePromise對象;如果未找到,則返回一個resolvefalsePromise對象。
  7. Cache.keys(request, options)
    返回一個Promise對象,resolve的結果是Cache對象key(request 對象)組成的數組。

ServiceWorker 的使用

  1. serviceWorkerContainer.register() 來註冊
  2. 註冊成功的話,會開啓另一個線程來做這件事。與我們的網頁是互不相干的。
  3. service worker 現在可以接收事件。
  4. service worker 控制的頁面打開後會嘗試去安裝 service worker
  5. 最先發送給 service worker 的事件是安裝事件(在這個事件裏可以開始進行填充 IndexDB和緩存站點資源),讓所有資源可離線訪問。
  6. oninstall 事件的處理程序執行完畢後,可以認爲 service worker 安裝完成了。
  7. service worker 安裝完成後,會接收到一個激活事件 onactivate 主要用途是清理先前版本的 service worker 腳本中使用的資源。
  8. Service Worker 現在可以控制頁面了,但僅是在 register() 成功後的打開的頁面。

ServiceWorker 的註冊

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
    // registration worked
    console.log('Registration succeeded. Scope is ' + reg.scope);
  }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
  });
}

微信公衆號

clipboard.png

總結

測試路徑
https://www.lilnong.top/stati...

  1. https
  2. SW 通過fetch來實現代理瀏覽器請求。
  3. SW 註冊之後會嘗試安裝。但是激活需要等下次(沒有再用的資源了)
  4. SW 要注意他限制的域
  5. importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'); 是一個封裝包
  6. vue-cli也有一些webpack支持的工具

    1. @vue/pwa
    2. @vue/cli-plugin-pwa

資料

  1. Service_Worker_API --mdn
  2. Service Workers --mdn
  3. cache --mdn
  4. AppCache --mdn
    這個內容我覺得不用再關心了 <html manifest="example.appcache">
  5. 前端每週清單半年盤點之 PWA 篇 ---王下邀月熊_Chevalier
  6. 傻傻分不清的Manifest
  7. PWA之 workbox 學習
  8. 初探PWA
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章