魔改 sw-precache
sw-precache
是一个用来生成预加载资源的 ServiceWorker 的 js 文件的模块。将它用到 Ghost 上后,发现它并不能正常工作,原来 Ghost 会自动给 asset
中的静态文件加上 ?v=#######
,而 sw-precache 里记录的是原始的文件名,并不匹配。所以对 sw.js 修改了一下。
// sw.js
var url = event.request.url;
if (/\.(js|css)(\?|$)/.test(url) && /^https?:\/\/(blog\.ihanai\.com|cdnjs\.cloudflare\.com)/.test(url)) {
event.respondWith(
caches.open(cacheName).then(function (cache) {
return setOfCachedUrls(cache).then(function (cachedUrls) {
// If we don't have a key matching url in the cache already, add it.
var cacheKey = event.request.url;
if (!cachedUrls.has(cacheKey)) {
return fetch(event.request).then(function (response) {
if (response.ok || response.type === 'opaque') {
cleanResponse(response).then(function (responseToCache) {
return cache.put(cacheKey, responseToCache);
});
}
return response.clone();
});
} else {
return cache.match(cacheKey).then(function (response) {
if (response) return response;
throw Error('The cached response that was expected is missing.');
})
.catch(function (e) {
console.warn('Couldn\'t serve response for "%s" from cache: %O', event.request.url, e);
return fetch(event.request);
});
}
});
})
);
}
这里有点需要注意的是使用 response.clone()
避免 TypeError。
当然,这样改了之后,功能变了,由原来的预加载资源文件变成了将部分文件使用 ServiceWorker 作缓存了。
最简单的方法还是修改 sw-precache 的配置,增加 ignoreUrlParametersMatching: [/^utm_/, /^v$/]
,这样 sw-precache
就能忽略 assetHash 了。由于生成的 sw.js
文件里有对资源 hash 的记录,所以忽略 Ghost 生成的 assetHash 并不会有什么不好的影响。
说点其它的,使用上面所说的方法将所以 js、css 资源文件用 ServiceWorker 缓存之后发现较 from disk cache 变慢了,原因在于随着 fetch 事件触发次数的增加,sw.js 中的一些代码如 setOfCachedUrls
、caches.open
执行了一次又一次,很多结果是相同的,但是并没有缓存,所以实际使用中可以考虑对其进行定制化修改。