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

Трек Офлайн-режим · Модуль №2

Архитектура офлайн-режима Cellestial ​

Сделано

Реализация и проверенные сценарии описаны в офлайн-режиме, связь инструментов и настроек — в сборке и регистрации SW. Ниже сохранён учебный план и его архитектурные объяснения.

Целевое устройство трека

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

Основа: SPA и BFF ​

Исходники frontend на SHA 6b4a7773e3cde056107dddd2912778b6a5691560 подтверждают основу: BFF добавляет персональный bootstrap в HTML и выставляет no-store, клиент читает bootstrap перед первым рендером, а прод-сборка использует отдельный CDN-каталог выпуска. Это факты о коде, без свидетельства выкладки: BFF и HTML, старт клиента, CDN в сборке.

У этой основы есть архитектурное следствие: сохранённый HTML может содержать данные пользователя, а запуск SPA зависит от bootstrap. Выбранная офлайн-страница должна быть самостоятельной. Контекст серверного HTML — в учебном документе «Серверный bootstrap».

Подготовка офлайн-режима ​

Пока сеть доступна, страница SPA инициирует регистрацию SW в браузере. Её JS может прийти с CDN: он выполняется в контексте страницы приложения на https://cellestial.ru. BFF не регистрирует SW — он публично раздаёт файлы, которые запрашивает браузер.

Целевые адреса: https://cellestial.ru/sw.js со scope / и https://cellestial.ru/offline.html. Браузер получает SW с BFF; во время установки SW заранее получает от BFF офлайн-страницу и все обязательные для неё ресурсы и сохраняет этот комплект в Cache Storage.

Регистрация сама по себе не гарантирует готовность: загрузка или сохранение комплекта могут прерваться. Активация SW и получение управления страницей — отдельные этапы жизненного цикла; успешная регистрация не означает, что текущая вкладка уже под его управлением.

Mermaid
mermaid
%%{init: {"sequence": {"actorMargin": 10, "width": 100, "wrap": true}}}%%
sequenceDiagram
  participant P as Страница SPA
  participant W as Браузер / SW
  participant B as Публичные файлы BFF
  participant C as Cache Storage
  P->>W: Инициировать регистрацию
  W->>B: Получить sw.js
  B-->>W: Код SW
  Note over W: Установка SW
  W->>B: Заранее получить<br/>offline.html и ресурсы
  B-->>W: Офлайн-комплект
  W->>C: Сохранить офлайн-комплект
  Note over W,C: Готовность требует SW,<br/>кеша и управления

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

Открытие с сетью ​

Целевое дополнение — SW, доступный после установки и получения управления страницей. Первое открытие может пройти без него. Основной поток остаётся сетевым: BFF формирует HTML, клиент получает ассеты и читает bootstrap до первого рендера; дальнейшие tRPC-запросы идут через BFF к Go API. Обращение BFF к Go при подготовке bootstrap зависит от состояния сессии.

Для навигации выбран NetworkOnly, с отдельной офлайн-подстановкой при сетевом отказе. Это не NetworkFirst: прошлый персональный HTML не используется как запасной ответ.

Полученные HTTP-ответы 401, 403, 404, 503 сохраняют смысл своего статуса. В частности, HTML 503 от BFF не заменяется офлайн-страницей автоматически: сервер вернул ответ. Сетевой отказ означает, что ответа получить не удалось; сам по себе он не доказывает отсутствие интернета у устройства. Различие статуса и отказа запроса объясняет MDN о Fetch.

Mermaid
mermaid
%%{init: {"sequence": {"actorMargin": 20, "width": 110, "wrap": true}}}%%
sequenceDiagram
  participant U as Браузер / SPA
  participant B as BFF
  participant G as Go API
  participant C as CDN
  Note over U,B: Целевой SW на пути навигации<br/>после установки и контроля
  U->>B: Навигация · NetworkOnly
  opt Нужны данные Go
    B->>G: Подготовка bootstrap
    G-->>B: Данные пользователя
  end
  B-->>U: HTML с персональным bootstrap
  U->>C: JS / CSS выпуска
  C-->>U: Публичные ассеты
  Note over U: Прочитать bootstrap<br/>Первый рендер SPA
  U->>B: tRPC · только сеть
  B->>G: Запрос API
  G-->>B: Результат
  B-->>U: Ответ RPC
  Note over U,B: SW не кеширует HTML и RPC

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

Открытие без сети ​

Повторное открытие может показать заранее сохранённую неперсональную офлайн-страницу. Для этого должны быть готовы и SW с подходящим scope, и кеш страницы вместе со всеми нужными ей ресурсами. Она не требует bootstrap, входа, запуска SPA или обращения к CDN для своего показа.

SW подставляет ответ под исходный адрес, без перенаправления на отдельный URL офлайн-страницы. Поэтому повторная попытка открывает нужную пользователю страницу. Это запасной неперсональный ответ на навигацию, а не восстановленная сессия и не сохранённый экран SPA. Понятие fallback — Workbox.

Mermaid
mermaid
flowchart TB
  URL["Повторное открытие исходного URL"] --> SW["SW управляет навигацией"]
  SW --> Net["Попытка получить HTML у BFF"]
  Net -->|"сетевой отказ"| Cache{"Офлайн-комплект в кеше?"}
  Cache -->|"да"| Offline["Неперсональная страница и её ресурсы"]
  Cache -->|"нет"| Error["Офлайн-показ не гарантирован"]
  Offline --> Show["Показ под исходным URL · без SPA и bootstrap"]
  Show --> Retry["Повторная попытка открыть исходный URL"]

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

Потеря сети в открытом приложении ​

Уже открытая SPA сохраняет текущий экран и показывает предупреждение о проблеме соединения. Автоматической замены экрана офлайн-страницей нет. Ошибка запроса не означает выход из аккаунта; сетевой сбой нельзя превращать в гостевую сессию.

navigator.onLine и события online / offline — подсказки для интерфейса. Доступность BFF определяет результат запроса к нему: локальная сеть может быть доступна, а BFF — нет, и наоборот. Отказ сервера не доказывает отсутствие интернета. HTTP-ошибка обрабатывается как HTTP-ошибка, а восстановление сигнала online ещё не доказывает успешность запроса. Ограничения индикатора — MDN.

Mermaid
mermaid
stateDiagram-v2
  state "SPA открыта" as Open
  state "Текущий экран + предупреждение" as Warning
  state "Проверка доступности BFF" as Check
  Open --> Warning: Сетевой отказ запроса или сигнал offline
  Warning --> Check: Повторная попытка / сигнал online
  Check --> Open: Запрос к BFF успешен
  Check --> Warning: Сетевой отказ
  state "Обработка HTTP-ошибки" as HTTP
  Check --> HTTP: Получен HTTP 4xx / 5xx
  HTTP --> Check: Повторная попытка

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

Что кешируем ​

Политика относится к типу ресурса и его содержимому. Наличие BFF само по себе не запрещает кеширование: персональный HTML исключён осознанным решением. Заголовок no-store не заменяет этого запрета в Cache API, как разобрано в теории.

РесурсКешируем в Cache StorageИсточник и выбранное поведение
Навигационный HTML BFFНетBFF; NetworkOnly, при сетевом отказе — отдельная офлайн-страница
RPC / APIНетBFF → Go API; NetworkOnly, ошибки остаются ошибками RPC
Офлайн-страницаДаПубличная статика BFF; precache во время установки SW
Обязательные ресурсы офлайн-страницыДаПубличная статика BFF; precache вместе со страницей
Остальные JS/CSS SPA и ассеты CDNНетCDN; загрузка по сети для обычной SPA

Персональный HTML, включая полученный HTML 503, ответы RPC и личные данные не кешируем; HTML в RPC не подставляем. Публичные версионированные ассеты SPA также не включаем в Cache Storage в выбранном минимальном сценарии: офлайн показывается только самостоятельный неперсональный комплект. Обычный HTTP-кеш браузера — отдельный механизм, эта таблица задаёт политику Cache Storage приложения. Сам sw.js браузер сохраняет как установленный Service Worker; это не запись в Cache Storage и не требование кешировать SW самим собой.

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

Размещение и обновление ​

SW, кеш и неперсональная страница образуют согласованный комплект. Адрес, scope, ответственность участников и правила для открытой вкладки — в размещении и обновлении.

Границы режима ​

  • Первый визит сразу без сети не гарантирует офлайн-страницу: сохранять её было некому.
  • Удалённый кеш или незавершённая установка дают тот же предел. Даже предыдущий онлайн-визит сам по себе не доказывает готовность комплекта.
  • Локальные данные может удалить пользователь или браузер — это нужно учитывать в сценариях проверки.

Сохранность Cache Storage — MDN.

Офлайн-страница не предоставляет личных данных, редактирования или фонового повторения записей. Кеширование личных данных технически возможно и с BFF, и без него, но потребовало бы отдельной продуктовой политики: что делать с истёкшей сессией, выходом и доступом другого человека к устройству. Этот трек такой политики не задаёт. Сетевая ошибка не заменяет решение сервера об авторизации.

Вопросы для реализации ​

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

Сценарии проверки ​

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

Далее — размещение и обновление, затем проверка офлайн-режима. Вернуться к теории офлайн-режима или к треку «Офлайн-режим».