如何确保从不激活的更新的Workbox缓存更新

问题描述 投票:0回答:1

我一直致力于将我们拥有的网络应用程序转换为PWA,而我正在使用Google的Workbox(v3.6.1)来预先缓存资源。在大多数情况下,它一直运行良好,但似乎有一个特定的情况导致缓存的文件不同步。

我使用基本的precacheAndRoute()功能来设置文件以进行预缓存。

workbox.precaching.precacheAndRoute([]); //populated at build time via workbox-cli

在首次安装和大多数更新时,文件将按预期进行预先缓存。但是,如果Service Worker实例当前是waiting并且安装了新的更新,则临时缓存中的所有挂起文件都将被删除,并且不会安装最新版本。

似乎workbox.precaching的安装步骤在将文件添加到临时缓存时更新了包含所有文件版本的IndexDB。因此,下一个Service Worker版本认为所有文件的先前最新版本当前都已缓存,即使它们仍然只在临时缓存中。然后新安装会在插入自己的文件之前从临时缓存中删除所有内容。因此,以前的waiting实例的挂起缓存文件将永远丢失。

我有一个想法,在安装新版本时,我可以强制临时缓存同步到永久缓存(通过使用PrecacheControlleractivate()函数),然后允许新实例进行预缓存,但我有一些担心更新用户正在使用该应用时永久缓存。

我正在寻找确认我的想法是一个合适的解决方案,或任何其他建议如何处理这种情况。

javascript workbox
1个回答
0
投票

Workbox最近发布了4.0.0版本,此问题似乎已通过该升级修复。我将留下以下答案,因为它对于此时无法升级到4.0.0的任何人仍然有用。


我使用PrecacheController或多或少地使用了这个,就像我在问题中提到的那样。一个讨厌的部分是我必须自己实施fetchactivate听众,因为我不再使用标准的workbox.precaching。如果有人有任何其他想法,请随意发布其他选项。

const precacheController = new workbox.precaching.PrecacheController();
precacheController.addToCacheList([]); //populated at build-time with workbox-cli

self.addEventListener('fetch', (event) => {
    var url = event.request.url.endsWith('/') ? event.request.url + 'index.html' : event.request.url;
    event.respondWith(new Promise(function (resolve) {
            if (precacheController.getCachedUrls().indexOf(url) > -1) {
                resolve(caches.open(workbox.core.cacheNames.precache)
                    .then((cache) => {
                        return cache.match(url);
                    })
                    .then((cachedResponse) => {
                        return cachedResponse || fetch(url);
                    }));
            } else {
                resolve(fetch(event.request));
            }
        }));
});

self.addEventListener('activate', (event) => {
    event.waitUntil(precacheController.activate());
    self.clients.claim();
});

self.addEventListener('install', function (event) {
    var timeoutId = null;
    event.waitUntil((new Promise(function (resolve, reject) {
                if (self.registration.waiting) {
                    var channel = new MessageChannel();
                    channel.port1.onmessage = function (event) {
                        resolve();
                    };

                    //tell the current 'waiting' instance to cleanup its temp cache
                    self.registration.waiting.postMessage({
                        action: 'cleanupCache'
                    }, [channel.port2]);
                } else {
                    resolve();
                }
            }))
        .finally(function () {
            //once temp cache is cleaned up from any 'waiting' instance, begin my install
            return precacheController.install();
        }));
});

self.addEventListener('message', function (event) {
    if (event.data.action === 'cleanupCache') {
    //move files from temp cache to permanent cache
        precacheController.activate().finally(function () {
            if (event.ports[0]) {
                event.ports[0].postMessage('cleanupComplete');
            }
        });
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.