Ситуации, в которых работник службы может отображать старую версию приложения даже после загрузки новой версии? - PullRequest
2 голосов
/ 20 сентября 2019

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

Проблема в следующем:

  1. Я развернул новую версию своего приложения
  2. Пользователь заходит на мой сайт, получает новую версию и успешно запускает ее
  3. Пользователь снова заходит на мой сайт и получает старую версию моего приложения

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

Подробнее:

Я использую Workbox 4.3.1,Мой обслуживающий работник в основном:

importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
workbox.precaching.precacheAndRoute([]);
workbox.routing.registerNavigationRoute("/index.html", {
    blacklist: [
        new RegExp("^/static"),
        new RegExp("^/sw.js"),
    ],
});

workbox.precaching.precacheAndRoute([]); заполняется на workboxBuild.injectManifest.Я могу вручную подтвердить, что нужные файлы заполнены. И, как правило, работник службы работает.Я вижу это в инструментах разработчика браузера.Я могу отключиться от Интернета и все еще использовать свое приложение.Все вроде нормально.Как я уже говорил выше, я никогда не видел, чтобы эта проблема возникала, и у меня нет воспроизводимого контрольного примера.

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

let registrations = [];
if (window.navigator.serviceWorker) {
    registrations = await window.navigator.serviceWorker.getRegistrations();
}
log({
    hasNavigatorServiceWorker:
        window.navigator.serviceWorker !== undefined,
    registrationsLength: registrations.length,
    registrations: registrations.map(r => {
        return {
            scope: r.scope,
            active: r.active
                ? {
                      scriptURL: r.active.scriptURL,
                      state: r.active.state,
                  }
                : null,
            installing: r.installing
                ? {
                      scriptURL: r.installing.scriptURL,
                      state: r.installing.state,
                  }
                : null,
            waiting: r.waiting
                ? {
                      scriptURL: r.waiting.scriptURL,
                      state: r.waiting.state,
                  }
                : null,
        };
    }),
})

Просматривая мои журналы, я вижу, что эта проблема возникает только для 1% моих пользователей.Firefox обогащен среди этих пользователей (4% общего трафика, но 18% записей журнала для этой проблемы), но это происходит для всех браузеров и операционных систем.

И я вижу, что почти все записи имеют эти значения:

{
    hasNavigatorServiceWorker: true,
    registrationsLength: 1,
    registrations: [{
        "scope": "https://example.com/",
        "active": {
            "scriptURL": "https://example.com/sw.js",
            "state": "activated"
        },
        "installing": null,
        "waiting": null
    }]
}

Насколько я знаю, это все правильные значения.

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

Итак, что может происходить?Как объяснить это наблюдаемое поведение?Что еще я могу записать для дальнейшей отладки?

Единственные сценарии, которые я могу придумать, кажутся мне крайне неправдоподобными.Например ...

  1. Пользователь загружает v1, по какой-то причине происходит сбой работника службы
  2. Пользователь загружает v2, по какой-то причине происходит сбой работника службы
  3. Пользователь каким-то образом получает v1 отих кеш браузера, так как все предыдущие работники сервиса не работали, но теперь работник сервиса работает правильно и сохраняет его как текущую версию

Но у меня нет никаких доказательств того, что работник сервиса когда-либо отказывал.Ничего в моих журналах ошибок.Ни один пользователь не жалуется на то, что поддержка в автономном режиме нарушена.

Если это поможет, фактический веб-сайт, где это происходит, - https://play.basketball -gm.com / , работник службы поддержки - https://play.basketball -gm.com / sw.js , и весь код доступен на GitHub .

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

1 Ответ

2 голосов
/ 29 сентября 2019

Каким-то образом пользователь получает старую версию из своего кэша.Удаление устаревших кэшей должно помочь.Как только новый работник службы установлен и предыдущая версия не используется, активируется новая, и вы получаете событие activate.Поскольку старая версия не подходит, самое время удалить неиспользуемые кеши.

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // Return true if you want to remove this cache,
          // but remember that caches are shared across
          // the whole origin
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
});

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

...