神奇的 Workbox 3.0

workbox 是 GoogleChrome 團隊推出的一套 Web App 靜態資源和請求結果的本地存儲的解決方案,該解決方案包含一些 Js 庫和構建工具,在 Chrome Submit 2017 上首次隆重面世。而在 workbox 背後則是 Service WorkerCache API 等技術和標準在驅動。在 Workebox 以前,GoogleChrome 團隊較早時間推出過 sw-precachesw-toolbox 庫,可是在 GoogleChrome 工程師們看來,workbox 纔是真正能方便統一的處理離線能力的更完美的方案,因此中止了對 sw-precache 和 sw-toolbox 的維護。css

從 sw-precache 和 sw-toolbox 的相關 issue 來看,衆多開發者對它們也是很有怨言。可是 workbox 發佈了 2.x 版本後其實反響通常,總的來講我認爲仍是 API 太混亂了,雖然功能很強大可是設計條理不清晰,其學習成本致使很難推廣開,可是從目前 workbox3 alpha 版本的文檔和 API 來看,我我的認爲 workbox3 終於成爲了可以很方便簡單的解決 Service Worker 絕大多數問題的神器,因此寫這篇文章來全面介紹一下。html

注意,當前 workbox 3 仍是 alpha 發佈階段,API 和接口還有可能調整,文中所提到的一些工具可能 Google 方面尚未徹底 ready, 本文爲正式發佈前的嚐鮮版,後續正式發佈後本會隨版更新。node

概述

workbox 如今已經發布到了 3.0 alpha 版本,咱們能夠先了解一下 workbox:webpack

  • 無論你的站點是何種方式構建的,均可覺得你的站點提供離線訪問能力。
  • 就算你不考慮離線能力,也能讓你的站點訪問速度更加快。
  • 幾乎不用考慮太多的具體實現,只用作一些配置。
  • 簡單卻不失靈活,能夠徹底自定義相關需求(支持 Service Worker 相關的特性如 Web Push, Background sync 等)。
  • 針對各類應用場景的多種緩存策略。

bingo! 若是你被這些特性吸引住了,能夠往下看看,咱們在這裏講的是 workbox 3.0 的內容,固然 workbox 在解決的核心問題方面和以前的版本沒有太大的出入,只是 API 進行了一些調整,而且在構建相關方面考慮的更加完善,workbox 進入 3.0 之後,API 看起來清晰多了,接下來一塊兒看看 workbox 3 具體內容吧。git

用法

想要使用 workbox,首先須要在你的項目中建立一個 Service Worker 文件 sw.js 而且在你的站點上註冊:github

123456789複製代碼
<script>// 能夠這麼註冊 Service Workerif ('serviceWorker' in navigator) {    // 爲了保證首屏渲染性能,能夠在頁面 load 完以後註冊 Service Worker    window.onload = function () {        navigator.serviceWorker.register('/sw.js');    };}</script>複製代碼

有了 sw.js 以後就可使用 workbox 了,你只須要在 sw.js 中導入 workbox 就可使用了:web

1234567891011複製代碼
// workbox 2.x 是將 workbox 核心內容放在 workbox-sw node_modules 包裏維護的// workbox 3.x 開始是將 workbox 核心 lib 放在 CDN 維護// 固然也能夠挪到本身的 CDN 維護importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0-alpha.3/workbox-sw.js');if (workbox) {    console.log(`Yay! workbox is loaded 🎉`);}else {    console.log(`Boo! workbox didn't load 😬`);}複製代碼

當在 sw.js 可以拿到 workbox 全局變量,代表 workbox 可使用了,workbox 能幹什麼呢?正則表達式

  • 經過 workbox.precaching 模塊來處理 Service Worker 靜態資源的預緩存。
  • 經過 workbox.routing 模塊提供的路由控制和 workbox.strategies 模快提供的緩存策略控制幫助你作動態緩存。
  • 使用 workbox 插件作一些 Service Worker 相對獨立的工做,好比 更新提醒, Background Sync 等

precache (預緩存) 靜態文件

若是你有一些靜態資源是須要永遠的離線緩存,除非從新上線才更新緩存的話,那 precache 預緩存應該是你所期待的,若是瞭解 Service Worker 的生命週期的話,precache 的工做是在 Service Worker install 時候經過 Cache API 完成的,具體能夠了解 Service Work 生命週期shell

workbox 提供了一種很是方便的 API 幫助咱們解決 precache 的問題,和以前 Google 的 precache 方案 sw-precache 的工做相似。workbox 經過使用 precaching.precacheAndRoute 接口完成 precache 操做:npm

12345678複製代碼
workbox.precaching.preacheAndRoute([    '/styles/index.0c9a31.css',    '/scripts/main.0d5770.js',    {        url: '/index.html',        revision: '383676'    },]);複製代碼

以上這段代碼會在 Service Worker 安裝成功的時候下載 /styles/index.0c9a31.css/scripts/main.0d5770.js, /index.html 文件,而且會以構造路由的方式將這些文件都存儲到 Cache Storage 中。這個傳入的數組其實就是預緩存內容列表,有兩種形式,一種是直接寫文件名的字符串(帶 Hash 的),一種是以下所示帶有 url 和 revesion 值的對象:

1234複製代碼
{    url: '將要預緩存的文件 URL, revision: '文件內容的 Hash 值'}複製代碼

這裏須要注意的是這個 revision 的值,當預緩存的文件就職何變更的時候就會被更新,若是 revision 沒有更新,那當你更新 Service Worker 的時候,被緩存的文件也不會被更新。

咱們接下來介紹一些幫助咱們生成預緩存內容列表的 precaching.precacheAndRoute API 的配置選項。

處理 / 和 /index.html

一般當用戶訪問 / 時,對應的訪問的頁面 HTML 文件是 /index.html,默認狀況下,precache 路由機制會在任何 URL 的結尾的 / 後加上 index.html,這就覺得着你預緩存的任何 index.html均可以經過 /index.html 或者 / 訪問到。

固然,你也能夠經過 directoryIndex 參數禁用掉這個默認行爲:

12345678910111213複製代碼
workbox.precaching.preacheAndRoute(    [        '/styles/index.0c9a31.css',        '/scripts/main.0d5770.js',        {            url: '/index.html',            revision: '383676'        },    ],    {        directoryIndex: null    });複製代碼

忽略請求參數

例如,若是我麼想要讓 key1 參數不是 /example.html?key1=1&key2=2 的一部分,你只須要設置 ignoreURLParametersMatching 參數把它排除掉:

1234567891011複製代碼
workbox.precaching.precacheAndRoute(    [        {            url: '/example.html?key2=2',            revision: '6821e0'        }    ],    {        ignoreUrlParametersMatching:[/key1/],    });複製代碼

這樣 /example.html?key1=1&key2=2 這個路由對應的內容就能夠被預緩存了。

生成預緩存列表

靠手動維護 precache.precacheAndRoute API 中的預緩存內容列表是不可能的,revision 咱們沒法手動維護,因此咱們確定是要藉助一些工具來幹這個事情,好在 workbox 提供了多種方式讓咱們選擇:

  • workbox 命令行
  • workbox-build npm 包
  • workbox-webpack-plugin

在使用以上三種方式生成預緩存內容列表以前,咱們先預設一下應用場景:假設你的項目在目錄 /app 下,必須保證在你的項目根目錄下有一個 app/sw.js 包含如下內容:

12複製代碼
// 一般項目中的 sw.js 源文件都是經過這樣預留一個空數組的方式來預緩存內容列表的workbox.precaching.precacheAndRoute([]);複製代碼

這樣才能保證能將生成的預緩存內容列表內容注入到 Service Worker 文件中。

workbox 命令行

workbox 提供了一套命令行,專門來幫助咱們注入預緩存內容列表,能夠幫助咱們生成注入預緩存內容列表所須要的 workbox-cli-config.js 配置文件,而後經過命令行使用配置文件就能夠生成一個預緩存列表的代碼並注入到以前自定義的 app/sw.js 文件中,最終編譯成線上所須要的 Service Worker 文件:dist/sw.js

安裝命令行:

1複製代碼
npm install -g workbox-cli複製代碼

因此咱們先要有一個 workbox-cli-config.js 文件,而後根據這個文件結合 /app/sw.js 源文件來生成一個含有預緩存列表的 dist/sw.js 文件。接下來咱們能夠看下具體這一系列流程須要怎麼操做。

首先執行 workbox generate:sw 命令生成一個配置文件 workbox-cli-config.js,這個命令執行以後將會彈出一些問題讓你選擇,以下所示:

12345複製代碼
>$ workbox generate:sw? What is the root of your web app? app? Which file types would you like to cache? (Press <space> to select, <a> to toggle all, <i> to inverse selection)html,ico,svg,png,js,css? What should the path of your new service worker file be (i.e. './build/sw.js')? dist/sw.js? Last Question - Would you like to save these settings to a config file? Yes複製代碼

回答完這些問題以後你就能夠在你的項目裏導出一個新的 workbox-cli-config.js 配置文件了大概長如下這個樣子:

123456789複製代碼
// workbox-config.jsmodule.exports = {    "globDirectory": "app/",    "globPatterns": [        "**/*.{html,ico,svg,png,js,css}"    ],    "swDest": "dist/sw.js",    "swSrc": "app/sw.js"};複製代碼

拿到了 workbox-cli-config.js 配置文件以後能夠執行 workbox inject:manifest workbox-cli-config.js 命令生成編譯後的 dist/sw.js 文件了,這一步乾的事情就是把預緩存內容列表注入到 app/sw.js 中,通常只有在上線前才用命令行注入預緩存內容列表,一般咱們都不會手動去執行這些命令的,比較合理的作法是實現生成好 workbox-cli-config.js 文件,而後在構建腳本中配置上自動執行 workbox inject:manifest 命令。

workbox inject:manifest 命令的作法就是去匹配 /app/sw.js 中的 workbox.precaching.precacheAndRoute([]) 方法的正則,而後經過 replace 內容注入的,能夠參考下面的 workbox-build 的介紹。

workbox-build

使用命令行總感受太傻了,操做步驟也比較繁瑣,爲了使得預緩存工做更加簡便靈活,workbox 也提供了一個 NPM 包 – workbox-build,你能夠在任何構建工具中都使用。

能夠在你的工程根目錄中執行如下命令安裝 workbox-build 包:

1複製代碼
npm install --save-dev workbox-build複製代碼

而後直接能夠在你想要處理 Service Worker 預緩存的地方引入 workbox-build 庫,而且調用其 injectManifest 方法:

12345678910111213141516171819複製代碼
const workboxBuild = require('workbox-build');workboxBuild.injectManifest({    swSrc: path.join(__dirname, 'app', 'sw.js'),    swDest: path.join(__dirname, 'dist', 'sw.js'),    globDirectory: './dist/',    globPatterns: ['**\/*.{html,js,css}'],    globIgnores: ['admin.html'],    templatedUrls: {        '/shell': ['dev/templates/app-shell.html', 'dev/**\/*.css'],    },    // 要替換的預留代碼區正則    injectionPointRegexp: /(\.precacheAndRoute\()\s*\[\s*\]\s*(\))/,}).catch(err => {    console.error(`Unable to inject the precache manifest into sw.js`);    throw err;});複製代碼

在構建文件中執行這段代碼就會讀取 app/sw.js 文件而後生成一個 dist/sw.js 文件含有注入的預緩存內容列表。

關於如何使用 injectManifest 方法能夠查看 workbox-build 的 injectManifest 方法 所有參數

workbox-webpack-plugin

有了 workbox-build 可想而知就能搞出不少實用的預緩存插件方案,好比 Webpack、Gulp 等插件,workbox 官方也提供了一個插件 workbox-webpack-plugin,只須要經過如下方式,就能夠將插件安裝到你的 webpack 項目中:

1複製代碼
npm install --save-dev workbox-webpack-plugin複製代碼

而後就只須要將插件添加到 Webpack 配置中就能夠正常使用了,插件參數和 workbox-build 的 injectManifest 方法保持一致:

123456789101112131415複製代碼
const workboxPlugin = require('workbox-webpack-plugin');// ...webpack({    plugins: [        // ...        new workboxPlugin({            swSrc: './src/sw.js',            swDest: './dist/sw.js',            globDirectory: './dist/',            globPatterns: ['**/*.{html,js,css}'],        })    ]    // ...});複製代碼

這裏有個地方和以前提到的替換預留的 app/sw.js 不同:使用 workbox 提供的 Webpack 插件必須在 app/sw.js 中包含如下代碼才能完成預緩存內容列表注入工做

1複製代碼
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);複製代碼

當插件跑起來以後,會在 /dist/sw.js 中增長一段 importScripts() 代碼用來引入一個模塊,這個模塊的內容就是 self.__precacheManifest,也就是預緩存內容列表的內容,具體的效果能夠在項目中使用 workbox-webpack-plugin 嘗試一下,看看 build 後的 dist/sw.js 結果就會比較清楚了。

路由請求緩存

路由請求緩存是經過文件路由匹配的模式分別對制定的路由文件作不一樣策略緩存的方式,這部分工做能夠在 app/sw.js 中直接使用 workbox 提供的 workbox.routing.registerRoute API 完成,這個 API 能夠理解爲幹了兩件事情,1、經過請求路由配置匹配到指定待緩存文件或請求內容2、經過第二個參數的處理回調函數決定用何種策略來緩存匹配上的文件。有 三種 方法能夠經過 workbox-route 來匹配一個請求 URL

  • 字符串方式
1234567891011複製代碼
// 能夠直接是當前項目下的絕對路徑workbox.routing.registerRoute(    '/logo.png',    handler // handler 是作緩存策略的回調函數,一般指後面所會降到的 '緩存策略函數');// 也能夠是完整的帶完整 host 的 URL 路徑,這裏的 URL 必須是 https 的workbox.routing.registerRoute(    'https://some-host/some-path/logo.png',    handler);複製代碼
  • 正則表達式方式
1234複製代碼
workbox.routing.registerRoute(    new RegExp('.*\.js'), // 這裏是任何正則都行,只要能匹配得上的請求路由地址    handler);複製代碼
  • 回調函數方式
12345678910複製代碼
// 經過回調函數來匹配請求路由將會讓策略更加靈活const matchFunction = ({url, event}) => {    // 若是請求路由匹配了就返回 true,也能夠返回一個參數對象以供 handler 接收處理    return false;};workbox.routing.registerRoute(    matchFunction,    handler);複製代碼

上面講到了匹配請求路由的三種方式,接下來能夠講講如何處理匹配上的請求所返回的內容,也就是上面三種路由匹配方式的 handler,一般有兩種作法:

  • 使用一種 workbox 經過 workbox.strategies API 提供的 緩存策略
  • 提供一個自定義返回帶有返回結果的 Promise 的回調方法。

路由請求緩存策略

下面介紹一下 workbox 默認提供的幾種緩存策略 API,這些 API 能夠被當成 handler 使用。

Stale While Revalidate

這種策略的意思是當請求的路由有對應的 Cache 緩存結果就直接返回,在返回 Cache 緩存結果的同時會在後臺發起網絡請求拿到請求結果並更新 Cache 緩存,若是原本就沒有 Cache 緩存的話,直接就發起網絡請求並返回結果,這對用戶來講是一種很是安全的策略,能保證用戶最快速的拿到請求的結果,可是也有必定的缺點,就是仍是會有網絡請求佔用了用戶的網絡帶寬。能夠像以下的方式使用 State While Revalidate 策略:

1234複製代碼
workbox.routing.registerRoute(    match, // 匹配的路由    workbox.strategies.staleWhileRevalidate());複製代碼

Network First

這種策略就是當請求路由是被匹配的,就採用網絡優先的策略,也就是優先嚐試拿到網絡請求的返回結果,若是拿到網絡請求的結果,就將結果返回給客戶端而且寫入 Cache 緩存,若是網絡請求失敗,那最後被緩存的 Cache 緩存結果就會被返回到客戶端,這種策略通常適用於返回結果不太固定或對實時性有要求的請求,爲網絡請求失敗進行兜底。能夠像以下方式使用 Network First 策略:

1234複製代碼
workbox.routing.registerRoute(    match, // 匹配的路由    workbox.strategies.networkFirst());複製代碼

Cache First

這個策略的意思就是當匹配到請求以後直接從 Cache 緩存中取得結果,若是 Cache 緩存中沒有結果,那就會發起網絡請求,拿到網絡請求結果並將結果更新至 Cache 緩存,並將結果返回給客戶端。這種策略比較適合結果不怎麼變更且對實時性要求不高的請求。能夠像以下方式使用 Cache First 策略:

1234複製代碼
workbox.routing.registerRoute(    match, // 匹配的路由    workbox.strategies.cacheFirst());複製代碼

Network Only

比較直接的策略,直接強制使用正常的網絡請求,並將結果返回給客戶端,這種策略比較適合對實時性要求很是高的請求。能夠像以下方式使用 Network Only 策略:

1234複製代碼
workbox.routing.registerRoute(    match, // 匹配的路由    workbox.strategies.networkOnly());複製代碼

Cache Only

這個策略也比較直接,直接使用 Cache 緩存的結果,並將結果返回給客戶端,這種策略比較適合一上線就不會變的靜態資源請求。能夠像以下方式使用 Cache Only 策略:

1234複製代碼
workbox.routing.registerRoute(    match, // 匹配的路由    workbox.strategies.networkOnly());複製代碼

不管使用何種策略,你均可以經過自定義一個緩存來使用或添加插件(後面咱們會介紹 workbox 插件)來定製路由的行爲(以何種方式返回結果)。

123456789複製代碼
workbox.strategies.staleWhileRevalidate({    // 使用用戶自定義的緩存名稱    cacheName: 'my-cache-name',    // 使用 workbox 插件    plugins: [        // ...    ]});複製代碼

固然,這些配置一般須要在緩存請求時更安全,也就是說,須要限制緩存的時間或者確保設備上用的數據是被限制的。

自定義策略

若是以上的那些策略都不太能知足你的請求的緩存需求,那就得想一想辦法本身定製一個合適的策略,甚至是不一樣狀況下返回不一樣的請求結果,workbox 也考慮到了這種場景(這也是爲何我會極力推薦 workbox 的緣由),固然,最簡單的方法是直接在 Service Worker 文件裏經過最原始的 fetch 事件控制緩存策略。也可使用 workbox 提供的另外一種方式:傳入一個帶有對象參數的回調函數,對象中包含匹配的 url 以及請求的 fetchEvent 參數,回調函數返回的就是一個 response 對象,具體用法以下所示:

1234567891011121314複製代碼
workbox.routing.registerRoute(    ({url, event}) => {        return {            name: 'workbox',            type: 'guide',        };    },    ({url, event, params}) => {        // 返回的結果是:A guide on workbox        return new Response(            `A ${params.type} on ${params.name}`        );    });複製代碼

第三方請求的緩存

若是有些請求的域和當前 Web 站點不一致,那能夠被認爲是第三方資源或請求,針對第三方請求的緩存,由於 Workbox 沒法獲取第三方路由請求的狀態,當請求失敗的狀況下 workbox 也只能選擇緩存錯誤的結果,因此 workbox 3 原則上默認不會緩存第三方請求的返回結果。也就是說,默認狀況下以下的緩存策略是不會生效的:

1234複製代碼
workbox.routing.registerRoute(    'https://notzoumiaojiang.com/example-script.min.js',    workbox.strategies.cacheFirst(),);複製代碼

固然,並非全部的策略在第三方請求上都不能使用,workbox 3 能夠容許 networkFirststalteWhileRevalidate 緩存策略生效,由於這些策略會有規律的更新緩存的返回內容,畢竟每次請求後都會更新緩存內容,要比直接緩存安全的多。

若是你強制使用 workbox 3 不推薦的緩存策略去緩存第三方請求,那 workbox 在 DevTools 裏的 console 中會報警報哦。

若是你仍是執意要緩存第三方請求的結果的話,workbox 3 也考慮到了確實會有這種難以扼殺的需求,提供了一個很是人性化的方式知足需求:利用 workbox.cacheableResponse.Plugin 來指定只緩存請求成功的結果,這樣就打消掉咱們以前對於不安全結果被緩存的顧慮了。鵝妹子英!(後面咱們會介紹插件機制)

1234567891011複製代碼
workbox.routing.registerRoute(    'https://notzoumiaojiang.com/example-script.min.js',    workbox.strategies.cacheFirst({        plugins: [            // 這個插件是讓匹配的請求的符合開發者指定的條件的返回結果能夠被緩存            new workbox.cacheableResponse.Plugin({                statuses: [0, 200]            })        ]    }),);複製代碼

workbox 配置

workbox 3 提供了一些配置項,都封裝在 workbox.core API 中,能夠稍微瞭解一下。

配置緩存名稱

經過 DevTools -> Applications -> Caches 能夠發現,workbox 對於緩存命名有一些規則的:

1複製代碼
<prefix>-<ID>-<suffix>複製代碼

每一個命名都有個前綴和後綴,中間纔是真正的命名 ID,主要是爲了更大限度的防止重名的狀況發生,能夠經過如下這種方式分別對 precache 和 runtime 形式的緩存進行自定義命名:

123456複製代碼
workbox.core.setCacheNameDetails({    prefix: 'my-app',    suffix: 'v1',    precache: 'custom-precache-name',// 不設置的話默認值爲 'precache'    runtime: 'custom-runtime-name' // 不設置的話默認值爲 'runtime'});複製代碼

經過以上設置後,precache 類型的緩存名稱爲 my-app-custom-precache-name-<ID>-v1,runtime 類型的緩存名稱爲 my-app-custom-runtime-name-<ID>-v1。workbox 推薦儘可能爲你的每一個項目設置不一樣的 prefix,這樣你在本地 locahost 調試 Service Worker 的時候能夠避免衝突。而 suffix 能夠用來控制緩存版本,讓站點的 Service Worker 更新機制變得清晰維護。

workbox 爲了讓 Web App 的緩存管理的更加細粒度的清晰可維護,也提供了策略級別的緩存命名設置,能夠經過策略 API 的 cacheName 參數進行設置:

123456複製代碼
workbox.routing.registerRoute(    /.*\.(?:png|jpg|jpeg|svg|gif)/g,    new workbox.strategies.CacheFirst({        cacheName: 'my-image-cache',    }));複製代碼

這樣,對應的圖片相關的 cacheFirst 策略的緩存都會以 my-image-cache-<ID> 的形式命名,這裏要注意的是:prefix 和 suffix 是不須要設置的

指定 development 環境

workbox 開發過程當中是須要 debug 的,因此 workbox 3 也提供了 logger 機制幫助咱們排查問題,可是在生產環境下,咱們不但願也產生 logger 信息,因此 workbox 提供了「指定當前環境」 的設置:

12345複製代碼
// 設置爲開發模式workbox.setConfig({debug: true});// 設置爲線上生產模式workbox.setConfig({debug: false});複製代碼

配置日誌 Level

workbox 3 提供 logger 機制幫助咱們更好的調試 workbox,一共有四種 log level:debuglogwarnerror

workbox logs

能夠經過如下方式設置 log 的 level,這樣就能夠只看到某個 level 的 log 信息,讓調試的過程當中更加專一。具體的設置方式是經過 worbox.core API 中的 setLogLevel 方法來完成:

1234567891011121314複製代碼
// 展現全部的 logworkbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug);// 只展現 log, warning 和 error 類型的 logworkbox.core.setLogLevel(workbox.core.LOG_LEVELS.log);// 只展現 warning 和 error 類型的 logworkbox.core.setLogLevel(workbox.core.LOG_LEVELS.warn);// 只展現 error 類型的 logworkbox.core.setLogLevel(workbox.core.LOG_LEVELS.error);// 啥 log 都沒有,這個適用於線上生產環境workbox.core.setLogLevel(workbox.core.LOG_LEVELS.silent);複製代碼

workbox 插件

插件機制應該是 workbox 3 最大的改進了,在 2.x 中,現有的插件大部分功能都是直接以 API 的形式拋給開發者,讓開發者一頭霧水,如今 3.0 中每一個內置插件本身封裝了以前的 API,對開發者來講專門解決了一個個獨立的問題。除此以外,workbox 3 還提供插件擴展機制以及事件鉤子可讓開發者本身擴展插件。workbox 插件可讓你經過操做一個請求的生命週期中的返回內容和請求內容添加其餘的一些行爲。

workbox 插件一般都是在緩存策略中使用的,可讓開發者的緩存策略更加靈活,workbox 內置了一些插件:

  • workbox.backgroundSync.Plugin: 若是網絡請求失敗,就將請求添加到 background sync 隊列中,而且在下一個 sync 事件觸發以前從新發起請求。

  • workbox.broadcastUpdate.Plugin: 當 Cache 緩存更新的時候將會廣播一個消息給全部客戶端,相似於 sw-register-webpack-plugin 作的事情。

  • workbox.cacheableResponse.Plugin: 讓匹配的請求的符合開發者指定的條件的返回結果能夠被緩存,能夠經過 status, headers 參數指定一些規則條件。

  • workbox.expiration.Plugin: 管理 Cache 的數量以及 Cache 的時間長短。

能夠像以下方式來使用 workbox 插件,以 workbox.expiration.Plugin 爲例:

123456789101112複製代碼
workbox.routing.registerRoute(    /\.(?:png|gif|jpg|jpeg|svg)$/,    workbox.strategies.cacheFirst({        cacheName: 'images',        plugins: [            new workbox.expiration.Plugin({                maxEntries: 60, // 最大的緩存數,超過以後則走 LRU 策略清除最老最少使用緩存                maxAgeSeconds: 30 * 24 * 60 * 60, // 這隻最長緩存時間爲 30 天            }),        ],    }),);複製代碼

自定義插件

固然,workbox 也知道這些插件確定不能知足你們的自定義策略的要求,因此索性將整個請求生命週期中的關鍵事件以事件鉤子回調函數的方式暴露出來,也就是說,咱們可使用這些事件鉤子打造本身更加靈活的 workbox 插件。一個插件就是一個構造函數,而鉤子就是以構造函數的方法的形式供開發者們自定義開發,下面介紹一下有哪些事件鉤子:

cacheWillUpdate

cacheWillUpdate({request, response}),在請求返回結果替換 Cache 結果以前被調用,你能夠在這個事件鉤子中在更新緩存以前修改返回的結果,若是將結果直接設爲 null 來避免當前請求的返回的結果被更新到緩存。

cacheDidUpdate

cacheDidUpdate({cacheName, request, oldResponse, newResponse}),當有新的緩存寫入記錄或者 Cache 緩存被更新時被調用,你能夠調用這個方法在 Cache 緩存更新以後乾點什麼。

cachedResponseWillBeUsed

cachedResponseWillBeUsed({cacheName, request, matchOptions, cachedResponse}),在 Cache 緩存的結果在 fetch 事件中被觸發響應返回以前調用,可使用這個回調來容許或阻止正在使用的 Cache 響應返回。

requestWillFetch

requestWillFetch({request}),當任何 fetch 事件被觸發的時候都會被調用,能夠在這個毀掉中修改請求的 request 內容。

fetchDidFail

fetchDidFail({originalRequest, request}),當 fetch 事件觸發失敗的時候被調用,fetch 事件觸發失敗是網絡根本沒法請求,而不是請求返回爲 非 200 的狀態的時候,能夠用這個鉤子在檢測到斷網的時候乾點什麼。

若是你想寫一個本身的 workbox 插件,只須要參照以下方式:

12345678複製代碼
// my-workbox-plugin.jsexport default const MyWorkboxPlugin = {    cacheWillUpdate({request, response}) {        // ... 搞事情    },    // ... 繼續搞事情};複製代碼

本文參考了 Google 官方文檔,在文檔的基礎上作了一些本身的解讀和總結,有興趣的開發者能夠閱讀原始文檔,文檔中還列出了一些「最佳實踐」以及 「debug」 的方式,能夠幫助咱們更好的使用 workbox。

相關文章
相關標籤/搜索