如何在登录后强制更新 PWA 缓存 [JS]?

How to force update PWA cache after login [JS]?

我有一个简单的论坛,我想离线使用。我有一个动态和静态缓存。静态缓存会填充安装事件和动态缓存,因为您会一直查看帖子。 问题是它缓存的页面包括 header 如果您已登录,则您有一个 link 到配置文件,如果您没有登录,则 link 到注册页面。 登录后它仍然显示注册 link 而不是个人资料 link。修复它的方法是刷新缓存?

有没有办法做到这一点,或者是否有其他解决此类问题的方法(除了网络优先方法之外)? 我是 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');
            });
        })        
    );
});

The way to fix it would be to refresh the cache?

没错,假设您缓存了路径 /login,Service Worker 将始终根据您的代码显示缓存在该路径下的内容。

Is there a way to do this or is there some other fix for this type of issue(besides network first approach)?

这并不是真正需要“修复”的东西,您所描述的是某种预期的行为。

解决这个问题有几种方法,网络优先只是一种方法:

  • 使用a message在登录时更新缓存
  • 在用户登录时使用不同的 url 或 url 查询等部分来跳过缓存
  • 根据用户状态隐藏客户端不需要的UI

可能还有很多。

这对我有用!

在尝试清空缓存之前,必须先成功安装服务工作者。因此,为了记录在案,您的 sw.js 文件应以通常的

开头
self.addEventListener("install", ...etc

现在我们要开始清理了。创建一个变量来存储您想要的缓存的名称 purge/update (使定位不同的缓存更容易)

var TargetCache= 'NameOfCacheToClean';

接下来,添加一个每次激活 service worker 时触发的 EventListener (activate-event 出现在页面 reload/refresh 上)

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())
  );
});

只是 in-case,我通常会在 fetch-requests 清除旧缓存的代码之后添加拦截传出的事件侦听器。

self.addEventListener('fetch', function(event) {...etc