Как обеспечить обновление кэша Workbox для обновлений, которые никогда не активируются - PullRequest
0 голосов
/ 08 февраля 2019

Я работал над преобразованием веб-приложения, которое у нас есть, в 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 будут потеряны навсегда.

У меня была идея, что при установке новой версии я могу принудительно синхронизировать временный кэш с постоянным (используя PrecacheController и функция activate()), прежде чем разрешить новому экземпляру выполнять предварительную кэш, но у меня есть некоторые опасения по поводу обновления постоянного кэша, пока пользователь активно использует приложение.

Яищу либо подтверждение того, что моя идея здесь является подходящим решением, либо любые другие предложения о том, как справиться с этим сценарием.

1 Ответ

0 голосов
/ 12 февраля 2019

Workbox недавно выпустила версию 4.0.0, и эта проблема, похоже, была исправлена ​​в этом обновлении.Я оставлю приведенный ниже ответ, так как он все еще может быть полезен для тех, кто не может обновить до 4.0.0 в настоящее время.


Я получил это более или менее с помощью PrecacheController, как я уже упоминалв вопросе.Одна досадная деталь в том, что мне пришлось самому реализовывать прослушиватели fetch и activate, так как я больше не использую стандарт 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');
            }
        });
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...