关于Cache API相对路径的疑问:caches.match()匹配兼容性
Service Worker 离线资源匹配问题解答
背景说明
已实现支持离线浏览的Service Worker,核心代码如下:
self.addEventListener("fetch", event => { event.respondWith( caches.match(event.request).then( cachedResponse => { return cachedResponse || fetch(event.request); } ) ); });
同时已完成根路径资源的缓存,代码如下:
const cacheAssets = await caches.open('necessary-files-v1'); const listOfFiles = [ "/somefolder/somepage.html", "/somefolder/somevisual.jpg", "/somefolder/someaudio.mp3" ]; await cacheAssets.addAll(listOfFiles);
两种离线场景对比
- 场景1:
somepage.html中用相对路径引用图片:<img src="somevisual.jpg"> - 场景2:
somepage.html中用根绝对路径引用图片:<img src="/somefolder/somevisual.jpg">
问题解答
是否必须采用场景2?
不是必须。首先要纠正一个常见误解:场景1中浏览器会自动把相对路径somevisual.jpg解析为绝对路径/somefolder/somevisual.jpg,和缓存的路径完全一致,正常情况下caches.match(event.request)是能匹配到缓存资源的。如果实际出现匹配失败,大概率是匹配规则的细节问题,而非路径写法本身的问题。
灵活处理的方法
如果确实遇到路径匹配异常的情况,可以通过以下方式优化Service Worker的匹配逻辑:
- 统一解析请求路径后匹配
把请求URL解析为根相对路径,再和缓存的路径做匹配,避免路径写法差异导致的问题:
self.addEventListener("fetch", event => { // 提取请求的根相对路径 const requestPath = new URL(event.request.url).pathname; event.respondWith( caches.match(requestPath).then(cachedResponse => { return cachedResponse || fetch(event.request); }) ); });
- 添加宽松匹配选项
如果是查询参数、响应头差异导致的匹配失败,可以给caches.match添加宽松匹配选项:
self.addEventListener("fetch", event => { event.respondWith( caches.match(event.request, { ignoreSearch: true, // 忽略URL中的查询参数 ignoreVary: true // 忽略响应头中的Vary字段差异 }).then(cachedResponse => { return cachedResponse || fetch(event.request); }) ); });
- 自定义缓存匹配逻辑
通过遍历缓存键,手动实现更灵活的匹配规则,比如忽略大小写、模糊匹配路径等:
self.addEventListener("fetch", event => { const requestPath = new URL(event.request.url).pathname.toLowerCase(); event.respondWith( caches.open('necessary-files-v1').then(cache => { return cache.keys().then(keys => { // 找到路径完全匹配的缓存键(忽略大小写) const matchedKey = keys.find(key => key.pathname.toLowerCase() === requestPath); return matchedKey ? cache.match(matchedKey) : fetch(event.request); }); }) ); });
内容的提问来源于stack exchange,提问作者BulliedByModeratorsAgain_Again
相关产品推荐
相关产品推荐

