1. 程式人生 > >sw-precache使用指南

sw-precache使用指南

文章目錄

Service Worker Precache是一個能自動生成Service Worker檔案的模組,你可以利用它來預先快取資源。它可以和你的構建過程整合在一起,一旦配置完成,它就可以識別你的站點中所有靜態資源(HTML,JavaScript,CSS,圖片等)並生成每個檔案內容的雜湊值。每個靜態資源的網址、版本資訊的雜湊值都儲存在生成的Service Worker檔案中,當客戶端發起向這些靜態資源的網路請求時,Service Worker會優先返回快取中的相應資源,並且當之後的構建過程中改變了這些資源後,Service Worker也會更新相應的資源。

優先從本地提供已經快取的靜態資源 ,使得你可以獲取你的網路應用程式所有關鍵的支援檔案而無需等待任何網路響應。

該模組可以在基於JavaScript的構建指令碼中使用,例如使用gulp編寫的指令碼,同時它也提供了命令列介面。你可以直接使用模組,或者如果你願意的話,也可以對sw-precache進行包裝以配合特定的構建環境,例如webpack。

sw-precache可以與sw-toolbox一起使用,sw-toolbox可以為動態資源提供更好的快取機制。

安裝

本地構建整合:

$ npm install --save-dev sw-precache

全域性命令列介面:

$ npm install --global sw-precache

準備工作

  1. 確保你的網站使用HTTPS訪問。Service Worker功能僅在通過HTTPS訪問的頁面上可用(在localhost也可以使用,以方便本地測試)。之所以會設定這個限制,
    Prefer Secure Origins For Powerful New Features
    一文描述了相關原理;
  2. 將sw-precache整合到你的構建指令碼中。它可以與gulp、Grunt或其他以node.js編寫的構建指令碼良好地配合。我們在demo 資料夾中提供了兩個例子,demo中的每個構建指令碼都有一個名為writeServiceWorkerFile()的函式,它顯示瞭如何使用對應的API。 這兩個指令碼都可以生成功能完備的JavaScript程式碼,這些程式碼負責預先快取和獲取你的網站離線工作時需要的所有資源。我們還提供了一個一個命令列介面,方便那些使用其它構建方式的人使用;
  3. 註冊service worker檔案
    。你需要將生成的JavaScript檔案註冊為控制你的網站的service worker。通常這隻需要在你的網站的頂級的入口頁面中完成,因為service worker一旦在根目錄註冊,就會自動包含根目錄以下的所有頁面。service-worker-registration.js是一個示例指令碼,它說明了註冊service worker以及處理各種生命週期事件的最佳實踐。

示例

專案的示例檔案gulpfile.js說明了如何在適當的環境中使用sw-precache(注意:這裡的示例檔案是demo資料夾下的,而不是根目錄下的)。我可以通過克隆此repo來執行示例,使用npm install下載依賴項,進入demo資料夾,執行npm bin 或者gulp serve-dist,然後訪問localhost:3000檢視效果。

還有一個示例Gruntfile.js,說明了如何使用Grunt中生成service worker。 雖然它不能像gulp一樣在本地執行。

這裡有一個更簡單的gulp示例,它假定你的網站的資源都位於app資料夾下,並且你想要快取所有的JavaScript,HTML,CSS和圖片檔案。

gulp.task('generate-service-worker', function(callback) {
  var path = require('path');
  var swPrecache = require('sw-precache');
  var rootDir = 'app';

  swPrecache.write(`${rootDir}/service-worker.js`), {
    staticFileGlobs: [rootDir + '/**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff}'],
    stripPrefix: rootDir
  }, callback);
});

這個任務將在app資料夾下建立service-worker.js檔案,你需要在使用這個檔案前在你的頁面裡註冊它,你也可以直接使用我們已經編寫好的service-worker-registration.js來進行註冊。

注意事項

  1. service worker應該是漸進增強的。如果你只在瀏覽器支援service worker時才註冊它(可以通過'serviceWorker' in navigator來判斷),那麼你可以在支援service worker的瀏覽器上獲得離線支援,但在不支援service worker的瀏覽器上,對應的離線支援的程式碼永遠不會被呼叫。如此,在老舊的瀏覽器上使用sw-precache並不會產生額外開銷。
  2. 只要service worker一安裝,所有預先快取的資源都會由service worker在一個單獨的執行緒中獲取,因而當你在dynamicUrlToDependenciesstaticFileGlobs選項中列出需要快取資源時需要謹慎,因為列出那些非必要的檔案,比如不是每個頁面都需要的圖片,會導致瀏覽器下載更多不必要的資料。
  3. 預快取所有型別的資源並沒有意義(見上一點)。其他快取策略,如在offline cookbook中概述的那些策略,可以和sw-precache結合使用,從而為你的使用者提供最好的體驗。如果你自己實現了額外的快取邏輯,請把程式碼放在一個單獨的JavaScript檔案中,並使用importScripts()方法來引入。
  4. sw-precache使用了快取優先策略,瀏覽器會會在沒有詢問伺服器的情況下返回檔案的快取版本。使用此策略時,一個建議的方案是,當有新內容可用時提醒使用者,並給予他們重新載入頁面以獲取新內容的機會(service worker已將新內容新增到快取中,並在重新整理頁面時顯示)。示例的service-worker-registration.js檔案說明了你可以通過關注service worker生命週期事件來觸發此類訊息。

命令列介面

對於那些不喜歡使用sw-precache作為gulp或Grunt構建系統的一部分的人,我們也提供一個命令列介面,它支援API中列出的選項,可以通過外部JavaScript檔案等方式引入各種配置。

注意:如果不使用相應的自動構建系統而是使用命令列,則每次對本地資源進行更改時,你都需要重新執行命令列。如果不重新執行sw-precache,則以前快取的本地資源將會一直使用。

如果沒有具體設定選項,則會使用預設值。例如,在包含你的網站內容的頂級目錄中,如果你想生成一個快取所有本地資源的·service-worker.js·檔案,則可以簡單地執行:

$ sw-precache

或者,如果您只想快取位於dist 資料夾(當前目錄中的子目錄)中的html檔案,則可以執行:

$ sw-precache --root=dist --static-file-globs='dist/**/*.html'

注意:一定要在對shell有特殊含義的引數值(例如上面示例命令列中的*字元)中使用引號。

最後,可以使用--config <file>來傳遞複雜的配置。檔案中的任何選項都可以通過命令列標誌覆蓋。 我們強烈建議通過module.exports傳遞一個外部JavaScript檔案來定義config。例如,假設有一個path/to/sw-precache-config.js檔案,其中包含:

module.exports = {
  staticFileGlobs: [
    'app/css/**.css',
    'app/**.html',
    'app/images/**.*',
    'app/js/**.js'
  ],
  stripPrefix: 'app/',
  runtimeCaching: [{
    urlPattern: /this\\.is\\.a\\.regex/,
    handler: 'networkFirst'
  }]
};

可以通過以下方式將該檔案傳遞到命令列介面,同時設定verbose選項:

$ sw-precache --config=path/to/sw-precache-config.js --verbose

這種方式靈活性最高,例如可以為runtimeCaching.urlPattern選項提供正則表示式。我們也支援傳遞--configJSON檔案,儘管這種方式靈活性要差一些:

{
  "staticFileGlobs": [
    "app/css/**.css",
    "app/**.html",
    "app/images/**.*",
    "app/js/**.js"
  ],
  "stripPrefix": "app/",
  "runtimeCaching": [{
    "urlPattern": "/express/style/path/(.*)",
    "handler": "networkFirst"
  }]
}

實時快取

有時候需要同時使用預先快取與實時快取。也許你知道我們的sw-toolbox工具,它可處理實時快取,但是想知道如何能同時使用sw-precache與sw-toolbox。幸運的是,sw-precache已經為你處理好了。

sw-precache模組可以引入sw-toolbox並且同時對它們進行配置。在sw-precache中使用runtimeCaching配置選項是一種更為便捷的配置方式,你不再需要手動引入sw-toolbox並編寫自己的路由規則。如果使用此選項,則使用指定的快取策略配置的sw-toolbox將自動包含在生成的service worker檔案中。

配置選項陣列中的每個物件都需要一個urlPattern,它是一個正則表示式或一個字串,遵循sw-toolbox的配置約定。此外,還需要一個handler,它應該對應於sw-toolbox內建的處理程式。可選的選項包括:新增方法以指定一個受支援的HTTP方法(預設值為get)。

例如,下面的配置為兩種不同URL模式定義了實時快取行為。它對兩種請求使用不同的處理程式,併為/articles/模式相匹配的請求指定了最大可用快取:

runtimeCaching: [{
  urlPattern: /^https:\/\/example\.com\/api/,
  handler: 'networkFirst'
}, {
  urlPattern: /\/articles\//,
  handler: 'fastest',
  options: {
    cache: {
      maxEntries: 10,
      name: 'articles-cache'
    }
  }
}]

sw-toolbox提供五種針對網路請求的處理程式(handler),具體如下表:

  1. networkFirst:首先嚐試通過網路來處理請求,如果成功就將響應儲存在快取中,否則返回快取中的資源來回應請求。它適用於以下型別的API請求,即你總是希望返回的資料是最新的,但是如果無法獲取最新資料,則返回一個可用的舊資料。
  2. cacheFirst:如果快取中存在與網路請求相匹配的資源,則返回相應資源,否則嘗試從網路獲取資源。 同時,如果網路請求成功則更新快取。此選項適用於那些不常發生變化的資源,或者有其它更新機制的資源。
  3. fastest:從快取和網路並行請求資源,並以首先返回的資料作為響應,通常這意味著快取版本則優先響應。一方面,這個策略總會產生網路請求,即使資源已經被快取了。另一方面,當網路請求完成時,現有快取將被更新,從而使得下次讀取的快取將是最新的。
  4. cacheOnly:從快取中解析請求,如果沒有對應快取則請求失敗。此選項適用於需要保證不會發出網路請求的情況,例如在移動裝置上節省電量。
  5. networkOnly:嘗試從網路獲取網址來處理請求。如果獲取資源失敗,則請求失敗,這基本上與不使用service worker的效果相同。

sw-toolbox選項中的cache選項可以指定快取的最大數目以及快取時間等,具體如下:

  1. cache.name[String]:用於儲存實時快取物件的快取名稱。使用唯一的名稱允許您自定義快取的最大空間和快取時間。預設值:在執行時根據service worker的registration.scope值生成。
  2. cache.maxEntries[Number]:對快取的專案實施least-recently快取過期策略,可以將此項用於動態資源快取。例如,將cache.maxEntries設定為10意味著在第11個專案被快取之後,最近最少使用的條目將被自動刪除。快取永遠不會超過cache.maxEntries規定的最大數量。此選項將僅在同時設定了cache.name時生效,它可以單獨使用或與cache.maxAgeSeconds一起使用。預設值為空。
  3. cache.maxAgeSeconds[Number]:強制規定快取專案的最大期限(以秒為單位),你可以用這個選項來儲存沒有自然過期策略的動態資源。例如,可以將cache.maxAgeSeconds設定為例如60 * 60 * 24,這意味著任何超過一天之前的快取都將被自動刪除。此選項僅在同時設定了cache.name時生效,它也可以單獨使用或與cache.maxEntries一起使用。預設值為空。