我有一个简单的论坛,我想让它离线工作。我有一个动态和静态的cahce。静态缓存会在安装事件中填充,而动态缓存则会在你浏览帖子时填充。问题是,它缓存的页面包括标头,如果您已登录,则在标头中可以链接到配置文件,如果您未登录,则可以链接到注册页面。登录后,它仍然显示注册链接,而不是配置文件链接。修复它的方法是刷新缓存?
有没有办法做到这一点,或者有没有其他解决这类问题的方法(除了网络优先的方法(?我对PWA还比较陌生,找不到任何有用的提示。
我的服务人员是这样的:
const staticCacheName = "ScroocCacheV1";
const dynamicCacheName = "ScroocDynamicCacheV1";
const assets = [
'/',
'/css/main_styles.css',
'/js/ui.js',
'/about',
'/policies',
'/register',
'/createTopic',
'/stats',
'/proposals',
];
const limitCacheSize = (name, size) => {
caches.open(name).then(cache => {
cache.keys().then(keys => {
if(keys.length > size) {
cache.delete(keys[0]).then(limitCacheSize(name, size));
}
});
});
}
const dynamicCacheLimit = 18;
// Install service worker
self.addEventListener('install', evt => {
evt.waitUntil(
caches.open(staticCacheName).then(cache => {
cache.addAll(assets);
})
);
});
// Activate event
self.addEventListener('activate', evt => {
evt.waitUntil(
caches.keys().then(keys => {
keys.map((key => {
if (key !== staticCacheName && key !== dynamicCacheName) {
return caches.delete(key); //Deleting the old cache (cache v1)
}
}))
})
)
});
// Intercept fetch
self.addEventListener('fetch', evt => {
evt.respondWith(
fetch(evt.request).then(fetchRes => {
return caches.open(dynamicCacheName).then(cache => {
return caches.match(evt.request).then(function(result) {
if (result) {
return result;
} else {
cache.put(evt.request.url, fetchRes.clone());
limitCacheSize(dynamicCacheName, dynamicCacheLimit);
return fetchRes;
}
});
});
}).catch(function() {
return caches.match(evt.request).catch((error) => {
console.log(error)
return caches.match('/img/fallbackImage.png');
});
})
);
});
这对我很管用!
在尝试清空缓存之前,必须首先成功安装服务工作程序。因此,为了记录在案,您的sw.js文件应该以通常的开头
self.addEventListener("install", ...etc
现在这是我们要清理的地方。创建一个变量来存储要清除/更新的缓存的名称(使针对不同缓存更容易(
var TargetCache= 'NameOfCacheToClean';
接下来,添加一个EventListener,它在每次激活服务工作者时触发(激活事件发生在页面重载/刷新上(
self.addEventListener('activate', event =>
{
const currentCaches = [TargetCache];
event.waitUntil
(
caches.keys()
.then(cacheNames => {return cacheNames.filter(cacheName => !currentCaches.includes(cacheName));})
.then(cachesToDelete => {return Promise.all(cachesToDelete.map(cacheToDelete => {return caches.delete(cacheToDelete);})); })
.then(() => self.clients.claim())
);
});
以防万一,我通常会在清除旧缓存的代码之后添加拦截传出获取请求的事件侦听器。
self.addEventListener('fetch', function(event) {...etc
修复它的方法是刷新缓存?
这是正确的,假设您缓存了路径/login
,服务工作者将始终根据您的代码显示该路径下缓存的内容。
有没有办法做到这一点,或者有没有其他解决此类问题的方法(除了网络优先的方法(?
这并不是真正的";fix";,你所描述的是一些意料之中的行为。
有几种方法可以解决这个问题,网络优先只是其中之一:
- 登录时使用消息更新缓存
- 当用户登录时,使用不同的url或url部分(如查询(跳过缓存
- 根据用户状态隐藏客户端上不需要的UI
可能更多。