Извините, у меня нет воспроизводимого тестового примера этой проблемы, потому что я сам никогда не видел, чтобы это происходило. Я знаю только, что это происходит из-за входа в мое приложение на стороне клиента и жалоб от пользователей.
Проблема в:
- Я развертываю новую версию своего приложения
- Пользователь заходит на мой сайт, получает новую версию и успешно ее запускает
- Пользователь снова заходит на мой сайт и получает старую версию моего приложения
Я использую сервис-воркер, который, как я надеялся, может дать некоторые гарантии того, что этого сценария не произойдет. Это особенно беспокоит, когда новая версия включает миграцию схемы 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, и при начальной загрузке он сравнивает этот номер версии с текущим номером версии. Если версия в 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, когда пользователь запрашивает новую версию.
Итак, что могло происходить? Как можно объяснить это наблюдаемое поведение? Что еще я мог регистрировать для дальнейшей отладки?
Единственные сценарии, которые я могу придумать, кажутся мне крайне неправдоподобными. Нравится...
- Пользователь загружает v1, сервис-воркер по какой-то причине не работает
- Пользователь загружает версию 2, сервис-воркер по какой-то причине не работает
- Пользователь каким-то образом получает v1 из кеша своего браузера, так как все предыдущие сервисные работники потерпели неудачу, но теперь сервисный воркер работает правильно и сохраняет это как текущую версию.
Но у меня нет свидетельств того, что сервис-воркер когда-либо терпел неудачу. В моих журналах ошибок ничего нет. Ни один пользователь не жалуется, что офлайн-поддержка не работает.
Если это помогает, то на самом деле это происходит на веб-сайте https://play.basketball-gm.com/, сервисный работник находится по адресу https://play.basketball-gm.com/sw.js, а весь код доступен на GitHub.
И эта проблема возникла с тех пор, как я начал использовать сервис-воркер около года назад. Я только что наконец приступил к написанию вопроса о переполнении стека, потому что я отказался от надежды, что смогу разобраться в нем самостоятельно или даже создать воспроизводимый тестовый пример.