沉醉在生命的優美。看着星,想象你本身跟它們在奔馳。——哲學家,馬克·奧勒留javascript
性能始終在時間與空間上相互權衡取捨,計算機系統的優化須要藉助各類緩存策略,從CPU到內存,從接口到外設。若是有一天,硬件成本和實現難度再也不是阻礙,也許便沒有了「優化」這個字眼。css
當下,前端面臨的優化與挑戰更多,複雜的終端環境,各類不一樣的瀏覽器內核,尺寸不一的瀏覽設備,兼容要作。複雜不穩定的網絡環境,愈來愈多的資源,優化要作。對於緩存,咱們並不陌生,可是咱們想有主觀意識的緩存,我想緩存什麼,緩存多久,緩存和請求資源的策略是什麼都有本身來定,service worker
能幫咱們作到。html
使用 service worker
前,須要建立一份註冊文件,不妨在項目下建立一個名爲 sw.js
的文件前端
console.log('Hello, I am sw.js file')
複製代碼
而後在應用中經過這個文件進行註冊,經過如下代碼就能完成應用中 service worker
的註冊,後面關於 service worker
相關的處理,在 sw.js
文件中進行java
<script> // 檢查當前瀏覽器是否支持service workers if ('serviceWorker' in navigator) { // 確保資源加載完成,再註冊service worker window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js'); }); } </script>
複製代碼
刷新頁面,就能看到控制檯打印了這句話,表示 service worker
註冊成功webpack
打開控制檯 Application
,一切在掌控之中, service worker
註冊成功web
到這裏完成了,完成了 service worker
的註冊,關於其相關的配置和處理,咱們一塊兒去 sw.js
文件中定義吧!正則表達式
Google推出的、標準統一api操做的、基於 service worker
的策略緩存庫,它有一下幾點讓人稱讚的特色npm
我想起了一句話,簡單的概念複雜化,通俗的概念神祕化,這是爲了展現本身的不凡,😆,開個玩笑。相信大多人看到這些概念是蒙的,咱們只須要圍繞一個概念:緩存 ,而且是策略性的,存什麼是能夠控制的,也給咱們開發離線應用提供了思路。api
還記得那個 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 || []);
複製代碼
到這裏,能想象經過咱們對於項目中資源的配置,支持離線訪問嗎?經過這些配置可以極大提高應用性能,策略,你要的纔是最美的。
我是合一,英雄再會!