沉醉在生命的優美。看着星,想象你本身跟它們在奔馳。——哲學家,馬克·奧勒留css
性能始終在時間與空間上相互權衡取捨,計算機系統的優化須要藉助各類緩存策略,從CPU到內存,從接口到外設。若是有一天,硬件成本和實現難度再也不是阻礙,也許便沒有了「優化」這個字眼。html
當下,前端面臨的優化與挑戰更多,複雜的終端環境,各類不一樣的瀏覽器內核,尺寸不一的瀏覽設備,兼容要作。複雜不穩定的網絡環境,愈來愈多的資源,優化要作。對於緩存,咱們並不陌生,可是咱們想有主觀意識的緩存,我想緩存什麼,緩存多久,緩存和請求資源的策略是什麼都有本身來定,service worker
能幫咱們作到。前端
使用 service worker
前,須要建立一份註冊文件,不妨在項目下建立一個名爲 sw.js
的文件webpack
console.log('Hello, I am sw.js file') 複製代碼
而後在應用中經過這個文件進行註冊,經過如下代碼就能完成應用中 service worker
的註冊,後面關於 service worker
相關的處理,在 sw.js
文件中進行web
<script> // 檢查當前瀏覽器是否支持service workers if ('serviceWorker' in navigator) { // 確保資源加載完成,再註冊service worker window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js'); }); } </script> 複製代碼
刷新頁面,就能看到控制檯打印了這句話,表示 service worker
註冊成功正則表達式
打開控制檯 Application
,一切在掌控之中, service worker
註冊成功npm
到這裏完成了,完成了 service worker
的註冊,關於其相關的配置和處理,咱們一塊兒去 sw.js
文件中定義吧!api
Google推出的、標準統一api操做的、基於 service worker
的策略緩存庫,它有一下幾點讓人稱讚的特色瀏覽器
我想起了一句話,簡單的概念複雜化,通俗的概念神祕化,這是爲了展現本身的不凡,😆,開個玩笑。相信大多人看到這些概念是蒙的,咱們只須要圍繞一個概念:緩存 ,而且是策略性的,存什麼是能夠控制的,也給咱們開發離線應用提供了思路。緩存
還記得那個 sw.js
文件嗎?如今咱們把中心放在它身上,由於後續相關的操做要在這個文件中進行,ready?go!
###導入Workbox
首先在 sw.js
第一行導入 workbox.js
語法以下
importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'); 複製代碼
這樣就導入成功了嗎?寫段代碼測試一下吧!
if (workbox) { console.log(`Yay! Workbox is loaded 🎉`); } else { console.log(`Boo! Workbox didn't load 😬`); } 複製代碼
更改完成後,回到瀏覽器,此時刷新瀏覽器沒有任何變化,這裏須要提醒一點,更改完 service worker
註冊文件須要終止重啓或者更新。
Workbox
定義了標準統一API,咱們來看如何藉助它提供的API逐步優化項目
在 Workbox
中,最核心的概念要數基於路由的策略緩存了,這裏抓住兩個關鍵詞,基於路由、策略 。接下來的重點即是放在如何基於路由,如何體現策略。
前端的大多資源都是經過 HTTP
請求得來的,包括 js
、css
、 圖片等等,既然這些內容都須要請求,那我能不能在請求發出後,作一些處理呢?就像房東租房,房東與租客之間的信息多是不對稱的,這時中介出現了,它可以在房東出租房子以前作一些處理,好比加收中介費。網頁在發起資源請求時,咱們也能夠作一些決定,是從緩存拿,仍是去請求。而針對不一樣的資源,正是經過資源請求地址來實現的,這即是__基於路由__,示例以下
workbox.routing.registerRoute( /\.js$/, … ); 複製代碼
以上代碼咱們定義了一個路由緩存策略,即:全部後綴爲 .js
的請求都會進入該策略進行處理,那,咱們須要作什麼處理呢?就會有針對匹配該路由的資源定義不一樣的關於緩存的策略,好比,咱們要求指定資源 網絡請求優先
workbox.routing.registerRoute( /\.js$/, new workbox.strategies.NetworkFirst() ); 複製代碼
此時若是在項目中引入了js文件,這個緩存便會生效,假設項目引入 hello.js
console.log('hello js file') 複製代碼
在html中引入
<script src="./hello.js"></script> 複製代碼
來到瀏覽器首先update一下service worker,方法上面介紹過這裏不贅述。緊接着刷新,咱們能夠看到打印的日誌,說明配置成功
萬事開頭難,咱們已經克服這第一道難題了,接下來先橫向拓展,針對不一樣類型文件的配置,選用不一樣策略。咱們先來看處理不一樣文件的配置,很簡單
workbox.routing.registerRoute( '/logo.png', handler // handler 是作緩存策略的回調函數,一般指後面所會降到的 '緩存策略函數' ); workbox.routing.registerRoute( 'https://some-host/some-path/logo.png', handler ); 複製代碼
workbox.routing.registerRoute( // 緩存圖片. /\.(?:png|jpg|jpeg|svg|gif)$/, handler ); 複製代碼
// 經過函數來匹配請求路由 const matchFunction = ({url, event}) => { // 若是請求路由匹配了就返回 true,也能夠返回一個參數對象以供 handler 接收處理 return false; }; workbox.routing.registerRoute( matchFunction, handler ); 複製代碼
上面代碼的handler是workbox提供的緩存策略API,經常使用的有如下幾種
策略名 | API |
---|---|
staleWhileRevalidate | 當請求的路由有對應的 Cache 緩存結果就直接返回,在返回 Cache 緩存結果的同時會在後臺發起網絡請求拿到請求結果並更新 Cache 緩存,若是原本就沒有 Cache 緩存的話,直接就發起網絡請求並返回結果 |
networkFirst | 網絡優先的策略 |
cacheFirst | 直接從 Cache 緩存中取得結果,若是 Cache 緩存中沒有結果,那就會發起網絡請求,拿到網絡請求結果並將結果更新至 Cache 緩存,並將結果返回給客戶端 |
networkOnly | 強制使用正常的網絡請求 |
cacheOnly | 直接使用 Cache 緩存的結果 |
通常場景下,以上5種策略基本能知足要求,若是還有不知足的狀況,可自定義策略
workbox.routing.registerRoute( ({url, event}) => { return { name: 'workbox' }; }, ({url, event, params}) => { // 返回的結果是:A guide on workbox return new Response( `I am ${params.name}` ); } ); 複製代碼
如下給出一個示例,介紹不一樣策略的使用方法
例如,圖片類資源,由於不太常更改,因此能夠選用優先緩存策略,併爲該類資源分組,具體內容能夠在 Application
-> Cache
查看
workbox.routing.registerRoute( /\.(?:png|jpg|jpeg|svg|gif)$/, new workbox.strategies.CacheFirst({ cacheName: 'my-image-cache', }) ); 複製代碼
js等相關文件能夠適當選擇網絡優先
workbox.routing.registerRoute( /\.html$/, new workbox.strategies.NetworkFirst() ); workbox.routing.registerRoute( /\.js$/, new workbox.strategies.NetworkFirst({ networkTimeoutSeconds: 3, }) ); 複製代碼
首先安裝 workbox-webpack-plugin
,選擇使用npm安裝
npm install --save-dev workbox-webpack-plugin
複製代碼
在webpack配置文件中配置該插件
const workboxPlugin = require('workbox-webpack-plugin'); // ... webpack({ plugins: [ // ... new workboxPlugin({ swSrc: './src/sw.js', swDest: './dist/sw.js', globDirectory: './dist/', globPatterns: ['**/*.{html,js,css}'], }) ] // ... }); 複製代碼
使用 workbox 提供的 Webpack 插件必須在 app/sw.js
中包含如下代碼才能完成預緩存內容列表注入工做
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
複製代碼
到這裏,能想象經過咱們對於項目中資源的配置,支持離線訪問嗎?經過這些配置可以極大提高應用性能,策略,你要的纔是最美的。
我是合一,英雄再會!