Я создаю ReactJs PWA, но у меня возникают проблемы с обнаружением обновлений на iOS.
На Android все работает отлично, поэтому мне интересно, связано ли все это с поддержкой iOS для PWA илиесли моя реализация работника службы не подходит.
Вот что я сделал до сих пор:
Процесс сборки и хостинг
Мое приложениепостроен с использованием веб-пакета и размещен на AWS.Большинство файлов (js / css) построены с хэшем в имени, сгенерированным из их содержимого.Для тех, кто не (app манифест, index.html, sw.js), я убедился, что AWS предоставляет им некоторые заголовки Cache-Control, предотвращающие любой кеш.Все обслуживается через https.
Service Worker
Я сохранил это как можно проще: я не добавил никаких правил кэширования, кроме предварительного кэширования для моей оболочки приложения:
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
Регистрация работника службы
Регистрация работника службы происходит в основном компоненте приложения ReactJs, в хуке жизненного цикла componentDidMount ():
componentDidMount() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then((reg) => {
reg.onupdatefound = () => {
this.newWorker = reg.installing;
this.newWorker.onstatechange = () => {
if (this.newWorker.state === 'installed') {
if (reg.active) {
// a version of the SW is already up and running
/*
code omitted: displays a snackbar to the user to manually trigger
activation of the new SW. This will be done by calling skipWaiting()
then reloading the page
*/
} else {
// first service worker registration, do nothing
}
}
};
};
});
}
}
Управление жизненным циклом работника службы
Согласно документации Google о работниках службы , при переходе к службе должна быть обнаружена новая версия работника службы.страница в области видимости.Но как одностраничное приложение, после его загрузки не происходит сложной навигации.
Обходной путь, который я нашел для этого, заключается в том, чтобы подключиться к реагирующему маршрутизатору и прослушать изменения маршрута, а затем вручную запроситьзарегистрированный работник сервиса для обновления:
const history = createBrowserHistory(); // from 'history' node package
history.listen(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.getRegistration()
.then((reg) => {
if (!reg) {
return null;
}
reg.update();
});
}
});
Фактическое поведение
Бросив кучу alert()
повсюду в коде, показанном выше, это то, что я наблюдаю:
- При первом открытии pwa после добавления его на домашний экран сервисный работник регистрируется должным образом на Android и iOS.
- . Оставляя приложение открытым, я устанавливаю новую версию на AWS.Навигация в приложении вызывает обновление вручную благодаря моему слушателю истории.Новая версия найдена, установлена в фоновом режиме.Затем отображается моя закусочная, и я могу переключиться на новое ПО.
- Теперь я закрываю приложение и развертываю новую версию в AWS.При повторном открытии приложения:
- На Android обновление обнаруживается сразу же, поскольку Android перезагружает страницу
- iOS не выполняет, поэтому мне нужно перейти в приложение, чтобы мой прослушиватель истории запустил поискдля обновления.При этом обнаруживается обновление
- После этого для обеих ОС отображается моя снэк-бар и я могу переключиться на новый SW
- Теперь я закрываюприложение и отключают телефоны.После развертывания новой версии я снова запускаю их и открываю приложение:
- На Android, как и раньше, перезагружается страница, которая обнаруживает обновление, затем отображается снэк-бар и т. Д.
- В iOS я перемещаюсь по приложению, и мой слушатель запускает поиск обновлений. Но на этот раз новая версия не найдена, и мой обработчик событий
onupdatefound
никогда не сработает
Чтение этой записина Medium от Maximiliano Firtman кажется, что iOS 12.2 принесла новый жизненный цикл для PWA.По его словам, когда приложение долго простаивает или во время перезагрузки устройства, состояние приложения уничтожается, как и страница.
Мне интересно, не может ли это быть основной причиной моей проблемы здесь, но я не смог найти никого, кто до сих пор сталкивался с такой же проблемой.