service-worker - Service worker: Cache by filename only not url
问题描述
I noticed that when you cache a file with a service worker
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
}
)
);
the file is cached based on the url
/bundle/v1/assets/icon.svg
But what I would like to have is only the file name on which the cache is base. Meaning that the same cache is used for
/bundle/v1/assets/icon.svg
/bundle/v2/assets/icon.svg
/bundle/v3/assets/icon.svg
Is something like this possible?
解决方案
您可以做的是在读取和写入缓存存储 API 时获得一些创意,方法是在将 URL 用作键之前对其进行规范化。
使用您的示例,假设您知道每次与以 结尾的 URL 的 Cache Storage API(读取或写入)交互时icon.svg
,您总是希望它引用相同的底层Response
,而不管完整的 URL。您可以执行以下操作:
// A "fake" prefix used for all the normalized entries.
// Choose something that is not used by your real URLs.
const NORMALIZED_PREFIX = '/__normalized/';
// A list of "files" whose URLs you want to normalize.
const FILES_TO_NORMALIZE = [
'icon.svg',
// ...anything else...
];
function normalizeUrl(request) {
// Convert the request.url string into a URL object,
// so that we can get the pathname cleanly.
const url = new URL(request.url);
for (const file of FILES_TO_NORMALIZE) {
if (pathname.endsWith(file)) {
// If we have a match, then normalize the URL by using our
// standard prefix along with the specific file name.
url.pathname = NORMALIZED_PREFIX + file;
return url.href;
}
}
// Otherwise, just return the original request's URL.
return request.url;
}
self.addEventListener('fetch', event => {
// This is a naive cache-first strategy. Customize to suit your needs:
// https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/
event.respondWith(async function() {
const requestKey = normalizeRequestUrl(event.request);
const cache = await caches.open('runtime-cache');
const cachedResponse = await caches.match(requestKey);
// If there's a cached response, use it.
if (cachedResponse) {
return cachedResponse;
}
// Otherwise, get a response from the network for the original request.
// Make sure you *don't* call fetch(requestKey),
// since that URL doesn't exist on the server!
const networkResponse = await fetch(event.request);
// When you save the entry in the cache, use cache.put()
// with requestKey as the first parameter.
await cache.put(requestKey, networkResponse.clone());
return networkResponse;
}());
});
推荐阅读
- c# - 如何将包含字符串的 Yaml 对象反序列化为列表
? - c# - 如何使用 C# 在 NPrinting Designer 的像素报告中更改单元格/组的背景颜色
- amazon-web-services - 如何在 Spring Boot 2 中为 CloudWatch 的 Micrometer 提供凭证
- appium - 如何在机器人框架脚本中使用 adb?
- node.js - 像 Charles 这样的 HTTPS 代理
- .net - linux 上 dotnet 的 Oracle 连接问题
- scala - 如何在高阶函数中将 @unchecked 用于选项
- c# - JSON 到字典 C# .Net 2.0 标准
- c# - 如何在 if 语句中测试多个变量?
- file - 如何查找文件夹的内容并将其删除到另一个文件夹中?