← Все статьи

SiteGuard12 мин чтения

Service Worker показывает старую версию сайта: как обновить кэш PWA

После публикации обновления сервер отдаёт новые файлы, а постоянные посетители продолжают видеть прежний интерфейс. В PWA причиной может быть Service Worker: он обслуживает открытые страницы и выбирает ответы из собственного кеша. Простое обновление вкладки не всегда меняет всю связку из страницы, worker и сохранённых ресурсов.

Если service worker не обновляет сайт, сначала установите, какая версия контролирует проблемную страницу и откуда получен конкретный ответ. Затем проверьте установку нового worker, его ожидание активации и переход открытых клиентов. Исправление должно сохранять введённые пользователем данные и совместимость приложения. Массовое удаление хранилищ не заменяет подготовленный механизм обновления.

Определите, какая часть PWA осталась старой

Словами «старая версия» могут описывать разные состояния: прежний HTML, старый JavaScript в памяти вкладки, устаревший ответ API или старый активный worker. Внешне они похожи, но требуют разных действий. Укажите конкретное расхождение: номер сборки, отсутствующий элемент интерфейса, содержимое файла или результат операции.

Полезно иметь отдельные диагностические признаки версии страницы и worker. Один постоянный адрес /sw.js не идентифицирует его содержимое: по этому адресу последовательно публикуются разные выпуски. Аналогично наличие кеша с названием новой версии не доказывает, что именно он обслуживает текущую вкладку.

Соберите минимальную карточку проблемы: URL страницы, время, ожидаемая сборка, фактическая сборка, браузер, наличие других открытых вкладок и состояние сети. Для разработчика добавьте адрес регистрации, scope и сведения о контроллере страницы. Так исследование будет опираться на воспроизводимое состояние, а не на предположение, что любой старый экран вызван кешем.

Проверьте scope, регистрацию и controller

Scope определяет область страниц, которую обслуживает регистрация Service Worker. Контроллер показывает, какой worker фактически управляет конкретной страницей. Эти сведения нужно рассматривать вместе: обнаруженная регистрация ещё не означает, что открытая вкладка уже находится под её контролем.

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

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

Также не считайте scope отдельной изолированной папкой кеша. Разные приложения одного origin могут использовать Cache Storage, поэтому очистка должна учитывать владельца каждого набора данных. Граница контроля страниц и правило удаления сохранённых ответов — разные решения проекта.

Сравните загрузку с перехватом и без него

В Chrome DevTools для PWA предусмотрен раздел Application для регистрации и кешей. Опция Bypass for network позволяет обойти Service Worker при запросах, а Update выполняет отдельную попытку обновления. Это разные инструменты: обход помогает локализовать источник ответа, обновление — проверить регистрацию.

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

Сравнение должно учитывать одинаковый URL и состояние авторизации. Ответ, полученный для другого аккаунта или другого пути, не доказывает исправность исходного сценария. Смотрите не только статус запроса, но и содержимое, заголовки, идентификатор сборки и источник ответа в инструментах браузера.

После проверки верните обычный режим. Успех при постоянно включённом обходе не означает, что посетители получат обновление. Для итоговой приёмки отключите отладочные принуждения, включая автоматическое обновление при каждой перезагрузке, и повторите переход так, как он происходит у реального клиента.

Обновление, установка и активация — разные этапы

Документация Chrome о жизненном цикле описывает установку нового worker рядом с действующим. После успешной установки обновление обычно ожидает, пока прежний worker перестанет контролировать клиентов. Такое ожидание помогает избежать неожиданной смены обработки запросов у уже открытого приложения.

Поэтому состояние waiting не обязательно означает поломку. Новый код может быть полностью подготовлен, пока пользователь продолжает работать в старой вкладке. Состояние active также не доказывает, что JavaScript, уже загруженный в память страницы, заменился новой сборкой. Для этого приложению нужен согласованный переход клиента.

Метод ServiceWorkerRegistration.update() запускает попытку обновления: браузер получает скрипт и проверяет изменение. Вызов не является командой немедленно перезагрузить страницы или очистить Cache Storage. После него проверяют результат установки, наличие ожидающего worker и дальнейшее состояние регистрации.

Если фактически опубликованный код worker не изменился, повторный вызов проверки не создаст ожидаемое обновление только потому, что команда изменила отдельную страницу. Сопоставьте содержимое worker, его список ресурсов и выпуск приложения. Для схемы с предварительной загрузкой эти части должны описывать согласованный комплект, а механизм обновления — действительно доставлять изменение до уже установленных клиентов.

НаблюдениеСледующая проверка
Новая версия не обнаруженаПроверить фактическое содержимое скрипта и правильную регистрацию
Установка началась, затем завершилась ошибкойНайти исключение и обязательный ресурс, который не удалось подготовить
Новый worker находится в waitingПроверить старых клиентов и предусмотренную политику обновления
Новый worker активен, экран прежнийСопоставить controller, сборку страницы и фактически выдаваемые ресурсы

Разберите провал install до попытки ускорить активацию

Если новая версия не установилась, команда skipWaiting не исправит отсутствующий файл или исключение в коде. Проверьте ошибки worker и запросы обязательных ресурсов. В подготовленной процедуре установки ошибка критичного шага должна приводить к понятному отказу обновления, а не к объявлению неполного набора готовым.

В обработчике install проверьте, что Promise всей обязательной подготовки передан в event.waitUntil(). Отклонение этого Promise прерывает установку новой версии. Запуск загрузки без ожидания её завершения или превращение ошибки в успешный результат не создают такой гарантии.

В учебном примере worker R18 должен подготовить оболочку и два обязательных пакета. Один пакет отсутствует в опубликованной сборке, поэтому операция установки отклоняется. Ожидаемый результат — продолжение работы проверенной R17 и доступная причина неудачи. Нельзя считать наличие созданного кеша R18 доказательством успешной установки.

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

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

Проверьте содержимое Cache Storage и правила его использования

Найдите конкретный запрос, который возвращает старую версию, и сопоставьте его с записью в Cache Storage. Затем проверьте логику worker: какой кеш он открывает, что ищет, при каких условиях обращается к сети и когда сохраняет новый ответ. Переименование кеша бесполезно, если обработчик продолжает искать в прежнем наборе.

Разделяйте ресурсы сборки и изменяемые данные. Для HTML, программных пакетов, изображений и ответов API могут требоваться разные правила актуальности. В частности, стратегия, подходящая неизменяемому файлу, не обязана подходить данным заказа. Обновление интерфейса не должно сохранять персональный ответ под общим ключом для разных пользователей.

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

Для ресурсов сборки полезны версионированные адреса, например app.71c2.js, связанные с конкретным HTML и списком предварительной загрузки. Проверяйте наличие всех файлов до предложения обновить клиента. Старые вкладки могут ещё запрашивать отложенно загружаемые части прежней сборки, поэтому их доступность нужно учитывать в политике публикации.

Удаляйте только собственные устаревшие кеши. Например, приложение магазина может владеть именами с согласованным префиксом shop-shell-; наличие рядом кеша другого приложения не разрешает его удаление. Перечень сохраняемых версий и момент очистки определяют по совместимости клиентов. Не копируйте правило «удалить всё, кроме нового кеша» на origin с несколькими приложениями.

Почему skipWaiting и clients.claim требуют проверки совместимости

Метод skipWaiting() позволяет новому установленному worker выйти из ожидания и перейти к активации. Это инструмент управления жизненным циклом. Он не заменяет сохранение пользовательского ввода и не гарантирует, что открытая страница понимает новую обработку запросов.

Метод clients.claim() позволяет активному worker взять подходящие страницы под контроль и вызывает событие controllerchange у клиентов, для которых контроллер изменился. При этом DOM и уже выполняемый JavaScript не превращаются автоматически в новую сборку. Страница может продолжить работу со старым кодом при новом обработчике запросов.

Представим учебную ситуацию: R17 загрузила основной интерфейс, пользователь позже открывает раздел, требующий старый дополнительный пакет, а новый worker уже удалил его кеш и изменил правила ответов. Даже корректно установленная R18 может нарушить этот переход. Поэтому ускоренная активация допускается после проверки таких сочетаний, а не как универсальный способ победить waiting.

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

Совместимость касается и серверного API. Сохранённая старая страница может успешно загрузить свои файлы, но отправить запрос по прежнему контракту. Поэтому срок поддержки клиента согласуют с серверными изменениями и форматом локальных данных. Обновление worker нельзя считать единственным механизмом, который мгновенно убирает из обращения все старые версии интерфейса.

Предложите обновление в безопасный момент

Пользователь не должен терять заполненную заявку из-за технического обновления PWA. Подготовьте понятное сообщение о доступной версии и действие «обновить после сохранения». До перезагрузки подтвердите сохранение работы предусмотренным способом. Наличие текста в поле или начавшийся сетевой запрос ещё не доказывают, что данные надёжно сохранены.

Команда должна определить поведение для активной отправки, незавершённого редактирования и офлайн-черновика. При необходимости предложение откладывают, пока операция не достигнет безопасного состояния. Механизм хранения черновиков и их совместимость с новой версией проверяют отдельно; обещание «всё восстановится» без такого механизма недопустимо.

Различайте сохранённый черновик и уже принятую сервером операцию. Если ответ на отправку потерялся перед обновлением, повторное открытие страницы не должно без проверки отправлять заявку ещё раз. Предусмотрите поиск результата по устойчивому идентификатору и понятное отображение неопределённого состояния. Эта проверка защищает от дублей при переходе клиента между версиями.

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

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

Учебный пример обновления в нескольких вкладках

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

ЭтапНаблюдениеОжидаемое решение
Обновление обнаруженоR18 в waiting, обе страницы ещё R17Показать ненавязчивое предложение и проверить незавершённую работу
Первая вкладка готоваВо второй остаётся несохранённая заявкаНе считать все клиенты готовыми к несовместимому переходу
Работа сохраненаЕсть подтверждение сохранения и согласованная готовностьВыполнить подготовленный переход к новой версии
Контроллер изменилсяWorker новый, код отдельных страниц ещё может быть прежнимЗагрузить согласованную сборку по логике приложения
Приёмка завершенаОбе страницы показывают R18 и читают сохранённую заявкуПодтвердить обновление и продолжить наблюдение

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

Почему unregister не равен очистке кеша и всех клиентов

Метод unregister() относится к регистрации Service Worker. Он не является общей командой удаления Cache Storage. Поэтому после снятия регистрации сохранённые ответы могут оставаться, а их удаление требует отдельного осознанного действия.

Кроме того, снятие регистрации нельзя трактовать как мгновенную замену уже открытых страниц. У существующих клиентов и выполняющихся операций есть собственное состояние; проверяйте контроллер конкретной вкладки и её последующую загрузку. Если код страницы снова регистрирует worker, регистрация может появиться заново. Без понимания этой последовательности результаты ручной проверки легко перепутать.

В рабочем исправлении необходимо решить, нужен ли Service Worker приложению дальше. Временное отключение на одном устройстве может помочь локализации, но не исправляет механизм обновления у аудитории. Если worker выводится из эксплуатации, подготовьте переход клиентов и судьбу собственных кешей, сохраняя нужные пользователю данные.

Не начинайте диагностику с полной очистки origin. Она уничтожит часть доказательств и может затронуть другие приложения или локальные черновики. Сначала установите причину, затем выполняйте адресное действие в согласованном тестовом окружении. Для посетителей предпочтительно исправление, доставляемое штатным механизмом приложения.

Выпускайте исправление новой версией worker

Если обновление оказалось неудачным, подготовьте новый выпуск worker, который возвращает проверенное поведение и учитывает уже существующих клиентов. Например, после R18 выпускается R19 с исправленным выбором ресурсов. Указание нового номера само по себе ничего не меняет: важны изменённый код, правильный набор файлов и проверенная процедура активации.

Перед таким возвратом проверьте, доступны ли ресурсы прежнего поведения и совместимы ли локальные данные. Старый кеш мог быть удалён, а открытая страница — уже начать работу по новой логике. Нельзя предполагать, что публикация прежнего HTML автоматически восстановит всё состояние PWA. Исправляющий выпуск должен обслуживать предусмотренные сочетания клиентов.

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

Чек-лист приёмки обновления PWA

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

  • Определены scope, контроллер страницы и фактическая версия её ресурсов.
  • Подтверждён обычный ответ и результат проверки без перехвата worker.
  • Успешная установка отличается от waiting и от завершённого обновления клиента.
  • Ошибка обязательного ресурса не оставляет посетителя с неполной новой сборкой.
  • Сохраняется работа пользователя, проверены несколько вкладок и отдельное окно PWA.
  • Старые клиенты получают нужные ресурсы в пределах согласованной совместимости.
  • Очистка ограничена собственными кешами, а регистрация проверена после повторной загрузки.
  • Исправляющий выпуск проходит тот же переход без отладочных обходов.

Для внешнего контроля HTTP-доступности опубликованного сайта используйте SiteGuard. Обновление Service Worker, состояние кешей и сохранность работы в PWA проверяйте отдельно при приёмке релиза.