一、ServiceWorker緩存文件
ServiceWorker是一種可以在瀏覽器後台運行JavaScript腳本的API,它能夠攔截網路請求並且將其轉化為來自緩存的響應。這意味著ServiceWorker能夠將資源緩存到本地,甚至可以使你的web應用離線使用!下面是一個簡單的示例:
// 註冊ServiceWorker
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/serviceworker.js').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
// 緩存文件
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('my-cache').then(function(cache) {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/script.js',
'/logo.png'
]);
})
);
});
// 返回緩存的響應
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
這段代碼向我們說明ServiceWorker如何緩存文件。在ServiceWorker註冊之後,它會通過install事件進行緩存。緩存文件的代碼片段如下:
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('my-cache').then(function(cache) {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/script.js',
'/logo.png'
]);
})
);
});
我們首先打開一個名為’my-cache’的緩存。然後通過cache.addAll()方法將我們需要緩存的文件添加到緩存中。在事件的最後,我們需要調用event.waitUntil()以確保ServiceWorker在緩存過程中不會被中止。
如果我們嘗試緩存已經存在的文件,如/,它將被忽略並不會影響後續步驟。一旦文件被成功緩存,我們可以在瀏覽器的開發工具中查看緩存的文件,如下圖所示:
二、ServiceWorker緩存大小
ServiceWorker緩存大小與其他類型的緩存一樣,是有限制的,不同瀏覽器之間也有所不同。
在Chrome中,ServiceWorker緩存的大小默認為50MB。在Firefox中,這個值默認為50MB,但是可以通過about:config進行更改。在Safari中,ServiceWorker緩存的大小默認為0,但是可以通過開啟web開發者模式進行更改。
當緩存大小達到最大限制時,ServiceWorker將無法緩存新的文件並且會刪除過期的文件以騰出空間。如果你使用緩存Api(caches.open()、cache.addAll()、cache.put()等),你可以通過cache.keys()方法查看緩存中的所有的鍵名並且去刪除過期的文件。
// 清空過期的文件
self.addEventListener('activate', function(event) {
var cacheKeeplist = ['my-cache'];
event.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (cacheKeeplist.indexOf(key) === -1) {
return caches.delete(key);
}
}));
})
);
});
上面的代碼展示了如何清空過期的文件。它通過event.waitUntil()方法來等待Promise的返回結果,以保證ServiceWorker不會在刪除過期文件時被中止。同時,我們只刪除名為’my-cache’的緩存,其他緩存不受影響。
三、ServiceWorker緩存文件版本控制
對於每次緩存文件的更新,為了防止瀏覽器緩存舊的文件,你需要對ServiceWorker進行版本控制。這可以通過在ServiceWorker文件中添加一個字元串版本號來實現。
下面是一個示例:
// 版本號
var CACHE_NAME = 'my-cache-v1';
// 註冊ServiceWorker
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/serviceworker.js').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
// 緩存文件
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME).then(function(cache) {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/script.js',
'/logo.png'
]);
})
);
});
// 返回緩存的響應
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
// 更新緩存
self.addEventListener('activate', function(event) {
var cacheKeeplist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (cacheKeeplist.indexOf(key) === -1) {
return caches.delete(key);
}
}));
})
);
});
我們在這個例子中添加了一個版本號——’my-cache-v1’,以避免緩存的文件與以前的版本相混淆。另外,在更新緩存時,應在緩存版本中更新版本號。
在實際開發過程中,當你進行任何修改時,都應該更改版本號。任何版本不同的ServiceWorker都將觸發activate事件,以便刪除舊緩存並更新到新緩存中。
在實際項目中,版本控制通常會涉及自動構建和更新版本號,以避免手動操作。
四、ServiceWorker緩存策略
緩存策略是指ServiceWorker決定返回哪個響應的演算法。通常,它根據請求的URL及請求方式(GET、POST、PUT等)進行決策。
常見的緩存策略有:
- networkFirst(網路優先):ServiceWorker優先檢查網路是否可用,如果網路正常,則從網路中獲取響應,如果網路不可用,則從緩存中獲取響應。
- cacheFirst(緩存優先):ServiceWorker優先檢查緩存是否存在請求的資源,如果存在,則從緩存中獲取響應,否則從網路中獲取響應。
- cacheOnly(僅緩存):ServiceWorker只從緩存中獲取資源,如果沒有緩存,則返回錯誤響應。
- networkOnly(僅網路):ServiceWorker只從網路中獲取資源,如果沒有網路,則返回錯誤響應。
- staleWhileRevalidate(過期更新):ServiceWorker優先從緩存中獲取響應,並將其返回給瀏覽器,然後在後台發送請求以獲取最新版本的響應,並更新緩存以供下次使用。
// 網路優先
self.addEventListener('fetch', function(event) {
event.respondWith(
fetch(event.request).catch(function() {
return caches.match(event.request);
})
);
});
// 緩存優先
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
// 僅緩存
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
);
});
// 僅網路
self.addEventListener('fetch', function(event) {
event.respondWith(
fetch(event.request)
);
});
// 過期更新
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('my-cache').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return response || fetchPromise;
});
})
);
});
上面的代碼展示了各種緩存策略的示例。你可以選擇一個適合你的需求的緩存策略來使用。
結論
通過ServiceWorker緩存機制,你可以輕鬆地將資源緩存到本地,使得你的Web應用可以離線使用。在不同瀏覽器中,ServiceWorker大小,版本控制方式和緩存策略會有所不同,因此你需要針對不同的瀏覽器進行優化。緩存策略應根據你的網站的需求進行選擇,以實現最佳的性能和用戶體驗。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/309718.html