我有一个动态URL的单页应用程序,它使用令牌构建,例如example.com/XV252GTH
,还有各种资源,如css、favicon等。
这是我注册Service Worker的方法:
navigator.serviceWorker.register('sw.js');
在名为sw.js
的文件中,我在安装过程中预缓存了资产:
var cacheName = 'v1';
var cacheAssets = [
'index.html',
'app.js',
'style.css',
'favicon.ico'
];
function precache() {
return caches.open(cacheName).then(function (cache) {
return cache.addAll(cacheAssets);
});
}
self.addEventListener('install', function(event) {
event.waitUntil(precache());
});
请注意,注册Service Worker的
index.html
页面只是一个模板,在发送到客户端之前会在服务器上填充;因此,在这个预缓存阶段,我只缓存模板而不是页面。现在,在fetch事件中,任何未在缓存中的请求资源都会被复制到其中:
addEventListener('fetch', event => {
event.respondWith(async function() {
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse;
return fetch(event.request).then(updateCache(event.request));
}());
});
使用此更新功能。
function updateCache(request) {
return caches.open(cacheName).then(cache => {
return fetch(request).then(response => {
const resClone = response.clone();
if (response.status < 400)
return cache.put(request, resClone);
return response;
});
});
}
在这个阶段,所有的资源都在缓存中,但动态生成的页面不在其中。只有在重新加载后,我才能看到缓存中的另一个条目:
/XV252GTH
。现在,应用程序已经具备离线功能;但是重新加载页面有点违背了整个Service Worker的目的。问题:我该如何从客户端(注册worker的页面)将请求(
/XV252GTH
)发送给SW?我猜我可以在sw.js
中设置监听器。self.addEventListener('message', function(event){
updateCache(event.request)
});
但是我怎么确定它会在时间上得到尊重,也就是说:客户端在软件安装完成后发送?在这种情况下,有什么好的做法呢?