MDN 文檔
- ServiceWorker
參考文章
- Working with the JavaScript Cache API
代碼地址
目標
斷網情況下正常打開頁面,加載本地緩存數據
調試
chrome 控制枱 > Application > Service Workers
創建 serviceWorker
新建 sw.js 文件,初始化監聽事件:
//sw.js
// 版本號
const CACHE_VERSION = 'cache-v0'
// 安裝
self.addEventListener('install', (event) => {
// sw.js 文件發生變動,就會執行 install 回調函數
console.log('install')
})
// 激活
self.addEventListener('activate', (event) => {
console.log('activate')
})
// 捕獲網絡請求
self.addEventListener('fetch', (event) => {})
register
註冊 serviceWorker:
navigator.serviceWorker.register("./sw.js",{scope:"/"}).then(
registration => console.log("success"),
error =>console.error("register error")
)
waitUntil
sw.js 文件發生變動後,雖然會執行 install 回調函數,但是新版本的腳本文件並沒有被激活。
激活 activate:
self.addEventListener('install', (event) => {
console.log('install')
//內容發生變化,直接進入 activate
event.waitUntil(self.skipWaiting());
})
caches
存在全局的 caches 對象,可通過 caches.open(cacheName) 打開緩存對象或delete(cacheName) 刪除對象。
通過 open 獲得 Cache 主要包含以下幾個方法:
| api | 作用 |
|---|---|
| Cache.addAll(requests) | 返回Promise,給 cache 添加緩存請求 |
| Cache.match(request, options) | 返回Promise,匹配緩存對象已緩存請求 |
| Cache.put(request, response) | 返回Promise,獲取請求和保存響應結果 |
更詳細的api介紹請查看 Working with the JavaScript Cache API
流程
ServiceWorker 需要在服務中啓用
首頁 index.html
- 加載樣式資源
index.css - 加載圖片資源
- 請求服務數據
data.json - 響應數據渲染進app標籤
- 註冊
ServiceWorker服務
<html>
<head>
<title>service Worker</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div id="app"></div>
<img
src="https://blog.logrocket.com/wp-content/uploads/2020/06/cacheapi.png"
/>
<script>
;(async () => {
const registration = await navigator.serviceWorker.register('./sw.js', {
scope: '/',
})
})()
window.onload = function () {
const xhr = new XMLHttpRequest()
xhr.open('GET', './data.json')
xhr.responseType = 'json'
xhr.onload = () => {
app.innerText = xhr.response.result
}
xhr.send(null)
}
</script>
</body>
</html>
sw.js 流程
- 聲明版本號
install
- 獲得對應版本號cache
- 添加需要緩存的資源路徑
- 進入 activate
activate
- 獲得已經註冊的caches版本
- 遍歷版本號,對比當前最新版本號
- 新舊版本號不匹配,清空舊版本
fetch
- 截取請求資源
- 打開當前版本號的緩存資源
- 匹配到緩存結果返回
- 不在緩存的資源再fetch服務器資源
- 如果是圖片資源,加入到緩存
// sw.js
const CACHE_VERSION = 'cache-v0'
// 只要 sw.js 發生變化,就會執行 install
self.addEventListener('install', (event) => {
console.log('install')
//內容發生變化,直接進入 activate
// event.waitUntil(self.skipWaiting());
// 進入緩存,添加緩存資源路徑,接着進入 activate
event.waitUntil(
caches
.open(CACHE_VERSION)
.then((cache) => cache.addAll(['/', '/index.css']))
.then(self.skipWaiting)
)
})
self.addEventListener('activate', (event) => {
console.log('activate')
// 默認情況下,首次加載後不受控制,self.clients.claim 讓首次控制生效
// event.waitUntil(self.clients.claim())
// 判斷緩存資源,如果緩存版本修改,刪掉舊版本資源
event.waitUntil(
caches.keys().then((cahceNames) => {
return Promise.all(
cahceNames.map((cacheName) => {
if (cacheName !== CACHE_VERSION) {
console.log('clear', cacheName)
return caches.delete(cacheName)
}
})
)
})
)
})
self.addEventListener('fetch', (event) => {
const url = event.request.url
event.respondWith(
caches.open(CACHE_VERSION).then(async (cache) => {
// 匹配緩存中的請求資源
let response = await cache.match(event.request)
// 存在則返回
if (response) return response
// 否則請求服務器資源
response = await fetch(event.request)
// 緩存服務器資源
if (/\.(jpg|png)$/g.test(url)) {
cache.put(event.request, response.clone())
}
return response
})
)
})