Перейти к содержимому
Загрузка статьи…

Офлайн-режим ​

Как получаются файлы и подключается SW, разобрано на странице Сборка и регистрация SW.

При повторном открытии Cellestial без сети браузер показывает заранее сохранённую неперсональную офлайн-страницу. Личные данные и редактор без сервера недоступны. Здесь объясняется, где хранится Service Worker (SW), чем отличаются три механизма хранения и что подтверждено на проде.

Где хранится Service Worker ​

После установки браузер сохраняет регистрацию и код SW во внутреннем хранилище браузерного профиля. Регистрация связывает origin, scope и URL скрипта. Это не файл приложения в localStorage и не запись, которую наш код добавляет в Cache Storage. Конкретное размещение файлов на диске — внутреннее устройство браузера, а не API приложения.

Сохранённый SW и выполняющийся контекст — разные вещи. Браузер может остановить контекст между событиями, а затем запустить его снова из сохранённого кода. Новое открытие вкладки не требует переустановки SW с нуля. Переменные остановленного контекста при этом не становятся постоянным хранилищем. Хранение регистрации и время жизни контекста — Chromium.

SW нужен безопасный контекст: HTTPS или допустимый локальный адрес разработки. Origin и scope определяют управляемые страницы. Установка PWA в отдельное окно и установка SW — самостоятельные процессы: наличие значка установки ещё не доказывает готовность офлайн-режима. Условия регистрации — MDN.

Mermaid
mermaid
%% Flowchart: регистрация сохраняется независимо от запускаемого контекста.
flowchart TB
  storedWorker[("Сохранены регистрация и код SW")]
  runningWorker["Браузер запускает контекст для события"]
  stoppedWorker["Контекст остановлен"]
  storedWorker -->|"нужно обработать событие"| runningWorker
  runningWorker -->|"браузер может завершить после работы"| stoppedWorker
  stoppedWorker -->|"новое событие · запуск из сохранённого кода"| runningWorker
  storedWorker -.->|"регистрация остаётся"| stoppedWorker
  classDef stored fill:#ddd6fe,stroke:#6d28d9,color:#374151
  class storedWorker stored

Загрузка схемы…

Три механизма хранения ​

МеханизмЧто хранитКто управляетГде смотреть в DevTools
HTTP-кешПолученные по HTTP ресурсы и сведения об их свежестиБраузер по HTTP-правилам, включая Cache-ControlNetwork: источник ответа и заголовки
Установленный Service WorkerРегистрацию, scope и установленный код SWБраузер через Service Worker APIApplication → Service workers
Cache StorageИменованные кеши с парами Request / ResponseСтраница или SW через Cache API; у нас — сгенерированный SWApplication → Cache storage

В Cache Storage ключом служит запрос, а значением — сохранённый ответ с телом и заголовками. Записи не обновляются и не удаляются по правилам HTTP-кеша автоматически. Даже Cache-Control: no-store не заменяет явного запрета сохранять личный ответ через Cache API. Браузер и пользователь могут удалить локальные данные; постоянную сохранность обещать нельзя. Cache API — MDN, HTTP-кеш — MDN.

Mermaid
mermaid
%% Flowchart: три независимых механизма одного браузерного профиля.
flowchart TB
  browserProfile["Браузерный профиль для origin"]
  browserProfile --> httpCache[("HTTP-кеш")]
  browserProfile --> workerStore[("Установленный SW")]
  browserProfile --> responseCaches[("Cache Storage")]
  headers["Правила HTTP"] -.-> httpCache
  workerApi["Service Worker API"] -.-> workerStore
  cacheApi["Cache API из страницы или SW"] -.-> responseCaches
  classDef store fill:#ddd6fe,stroke:#6d28d9,color:#374151
  class httpCache,workerStore,responseCaches store

Загрузка схемы…

Disable cache и обновление SW ​

Флажок Network → Disable cache отключает использование обычного HTTP-кеша при открытых DevTools. Он не удаляет установленный SW и записи Cache Storage. Поэтому отключённый HTTP-кеш совместим с уже существующей регистрацией и сохранённой офлайн-страницей. Отключение HTTP-кеша — Chrome DevTools.

Использование установленного SW и проверка новой версии — отдельные операции. Браузер проверяет обновления, в том числе при навигации в scope. Если содержимое скрипта изменилось, начинается установка новой версии. Отсутствие строки sw.js в конкретном списке Network само по себе не доказывает ни отсутствие регистрации, ни отсутствие фоновых проверок. Обновления SW — Chrome.

Для проверки последовательно:

  1. Открой Application → Service workers: проверь URL, scope, активную версию и управление страницей.
  2. В Cache storage отдельно проверь сохранённые ответы. Сам sw.js там искать не нужно.
  3. Для отладки обновлений включи Update on reload. Это специальный режим жизненного цикла, который повторно получает и устанавливает SW при перезагрузках; после проверки выключи его.
  4. При проверке офлайна отключай сеть также для запросов самого SW. Во время описанного ниже прогона сеть была отключена для страницы и контекста SW; отсутствие сети у одной страницы не считалось доказательством отказа запросов воркера.

Unregister удаляет регистрацию SW, а очистка Cache storage удаляет сохранённые ответы. Это разные действия. Для полного сброса данных выбранного сайта есть Clear storage. Инструменты проверки PWA — Chrome DevTools.

Как работает Cellestial ​

Клиент остаётся SPA с server bootstrap: BFF формирует HTML с начальными данными до первого рендера, а JS/CSS приходят с CDN. Полный запуск редактора офлайн здесь не обещается. В коде проверенного выпуска выбрана отдельная страница, которой не нужны сессия, bootstrap и файлы SPA.

BFF публично отдаёт /sw.js, /offline.html и манифест перед обработчиком персонального HTML: список файлов, порядок маршрутов.

РесурсВ Cache StorageПоведение реализованного SW
Персональный HTML BFFНетНавигация через сеть; при сетевом отказе — неперсональная подстановка
RPC / APIНетОтветы не сохраняются, HTML офлайн-страницы вместо RPC не возвращается
offline.htmlДаЗаранее сохраняется при установке SW
manifest.webmanifestДаПлагин добавляет публичный манифест в precache
JS/CSS и остальные ассеты SPAНетОбычная загрузка с CDN; HTTP-кеш рассматривается отдельно

Для навигации используется NetworkOnly с офлайн-подстановкой при отказе сети. Полученный HTTP-ответ, включая 503, остаётся ответом сервера: статус ошибки и сетевой отказ различаются. Правила заданы в конфигурации сборки SW.

В уже открытой SPA отказ соединения показывает предупреждение поверх текущего экрана. По коду выпуска его снимает только полностью полученный ответ BFF; событие online запускает проверку, а переход к доступному BFF показывает краткий тост «Соединение восстановлено». Учёт состояния соединения.

Mermaid
mermaid
%% Flowchart: подстановка применяется к отказу навигации, а не к статусу HTTP.
flowchart TB
  navigation["Навигация под управлением SW"] --> networkOnly["NetworkOnly · запрос BFF"]
  networkOnly --> gotResponse{"Получен HTTP-ответ?"}
  gotResponse -->|"да · включая 503"| serverResponse["Показать ответ сервера"]
  gotResponse -->|"нет · сетевой отказ"| savedPage{"offline.html есть в Cache Storage?"}
  savedPage -->|"да"| offlineResponse["Офлайн-страница под исходным URL"]
  savedPage -->|"нет"| unavailable["Офлайн-показ не гарантирован"]
  classDef decision fill:#fef3c7,stroke:#b45309,color:#374151
  classDef success fill:#a7f3d0,stroke:#047857,color:#374151
  classDef error fill:#fecaca,stroke:#b91c1c,color:#374151
  class gotResponse,savedPage decision
  class serverResponse,offlineResponse success
  class unavailable error

Загрузка схемы…

Проверка на проде ​

02.11.2026, 01:46 UTC+3, Chrome на Ubuntu, чистый браузерный профиль, гостевой сценарий на cellestial.ru. SHA из HTML: e3b327f58f8ef929afe0403ed7c7487abba2c48d.

СценарийНаблюдение
Открытие с сетьюФорма входа отрисована; /sw.js активен, scope /, страница имеет controller
Проверка Cache StorageТолько offline.html и manifest.webmanifest с ревизиями precache
МанифестChrome не сообщил ошибок манифеста и критериев установки
Сеть отключена у страницы и SW, повторное открытие /loginОфлайн-страница под тем же URL; ноль скриптов и внешних ресурсов
Сеть восстановлена, нажато «Повторить»Форма входа снова отрисована

Отдельно 02.11.2026, 00:28 UTC+3, на том же SHA: в графическом Chrome подтверждён нативный диалог Install. Результат выбора — accepted; приложение открылось отдельным окном, display-mode: standalone подтвердился, окно управлялось https://cellestial.ru/sw.js. Временный профиль и созданные для проверки файлы интеграции с ОС удалены.

Границы проверки ​

  • Проверен гостевой сценарий Chrome на Ubuntu. Safari, iOS, Android и другие браузеры этим прогоном не подтверждены.
  • Авторизованные операции, данные блокнотов и доступность Go API здесь не проверялись.
  • Обновление между двумя продовыми выпусками и тост восстановления соединения этим гостевым прогоном не проверялись; выше их устройство описано по коду конкретного SHA.
  • Первый визит без сети, удаление регистрации или кеша, незавершённая установка SW не гарантируют офлайн-страницу.
  • Офлайн-страница не предоставляет личные данные и не ставит действия пользователя в очередь.

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