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

Сборка и регистрация SW ​

Настройки сборки создают код Service Worker, а код страницы сообщает браузеру, где этот SW взять. В Cellestial обе части связывает адрес /sw.js. Ниже — пакеты и путь от настройки до выполнения по frontend e3b327f58f8ef929afe0403ed7c7487abba2c48d; наблюдения на проде и границы режима — в обзоре офлайн-режима.

Семейство Workbox ​

Workbox — семейство npm-пакетов, а не один скрипт, который целиком выполняется в браузере. Сборщик использует одни пакеты, страница — другие, сгенерированный SW — нужные части третьих.

ПакетГде работаетНазначение в нашем устройстве
workbox-buildПри сборкеПо настройкам создаёт SW и список предварительно сохраняемых файлов
workbox-windowНа страницеПомогает регистратору подключить SW и отслеживать его жизненный цикл
workbox-coreНа странице и в SWОбщие вспомогательные механизмы для других пакетов Workbox
workbox-routingВ SWВыбирает обработчик для подходящего запроса
workbox-strategiesВ SWДаёт стратегию NetworkOnly для навигации
workbox-precachingВ SWУправляет сохранением офлайн-страницы и манифеста с их ревизиями

Другие пакеты решают дополнительные задачи: workbox-expiration ограничивает срок и число записей, workbox-background-sync помогает с повтором запросов. Их наличие среди установленных зависимостей не означает, что эти возможности включены в Cellestial. Модули Workbox.

Прямые и транзитивные зависимости ​

В package.json клиента напрямую объявлены workbox-window в dependencies и vite-plugin-pwa в devDependencies. Первый нужен клиентскому коду регистрации, второй подключается как инструмент Vite.

workbox-build объявлен в зависимостях самого vite-plugin-pwa. Bun устанавливает его транзитивно: свой package.json есть у каждого пакета. bun.lock фиксирует версии и связи всего получившегося дерева, а не только непосредственные зависимости проекта.

Ниже упрощённый граф npm-зависимостей для vite-plugin-pwa@2.0.0 и Workbox 7.4.1. Стрелка означает «зависит от пакета или указанной группы пакетов»; это не порядок выполнения. Пакеты без префикса Workbox и часть внутренних связей опущены.

Связи подтверждены bun.lock выпуска и метаданными опубликованных пакетов: vite-plugin-pwa, workbox-build, workbox-window.

Установленный пакет не означает загруженный в браузер код. В бандл попадают зависимости, достижимые из импортов соответствующей точки входа, с учётом работы сборщика. Поле devDependencies само по себе не является запретом на включение импортированного кода в бандл. workbox-build выполняет сборочную работу; нужные модули Workbox включаются в полученный SW, а workbox-window — в клиентский JS. Прямая зависимость клиента явно обеспечивает импорт из виртуального модуля, не полагаясь на доступность чужих транзитивных пакетов.

Mermaid
mermaid
%% Flowchart: дерево установки пакетов, не состав браузерного бандла.
flowchart TB
  client["Клиент · package.json"] -->|"devDependencies"| pwaPlugin["vite-plugin-pwa"]
  client -->|"dependencies"| windowLibrary["workbox-window"]
  pwaPlugin --> buildLibrary["workbox-build"]
  pwaPlugin --> windowLibrary
  buildLibrary --> windowLibrary
  buildLibrary --> runtimeModules
  buildLibrary --> otherModules["Другие пакеты Workbox · сокращено"]
  subgraph runtimeModules["Часть прямых dependencies workbox-build"]
    precaching["workbox-precaching"] --> routing["workbox-routing"]
    precaching --> strategies["workbox-strategies"]
    routing --> core["workbox-core"]
    strategies --> core
    precaching --> core
  end
  windowLibrary --> core
  classDef build fill:#fed7aa,stroke:#c2410c,color:#374151
  classDef page fill:#a7f3d0,stroke:#047857,color:#374151
  class pwaPlugin,buildLibrary build
  class windowLibrary page

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

Что делает vite-plugin-pwa ​

vite-plugin-pwa связывает Vite с генерацией манифеста, SW и регистратора страницы. В режиме generateSW, выбранном в этом выпуске по умолчанию, workbox-build создаёт dist/sw.js по объекту workbox. Стратегии, условия обработки запросов, precache и его ревизии превращаются в исполняемый JavaScript.

Плагин поддерживает и injectManifest: разработчик пишет SW, а инструменты внедряют список precache в предусмотренную точку. Это другой способ подготовки файла, а не отдельная стратегия ответа на сетевые запросы. Здесь используется generateSW. Режимы плагина, генерация SW.

Виртуальный модуль регистрации ​

В src/serviceWorker.ts используется импорт:

apps/client/src/serviceWorker.ts · импорт
ts
import { registerSW } from 'virtual:pwa-register';

virtual:pwa-register — модуль, который предоставляет Vite-плагин. Физического файла проекта с таким именем нет: плагин перехватывает импорт и подставляет реализацию регистратора. При сборке в неё попадают URL SW, scope и настройки поведения страницы. Браузер не запрашивает virtual:pwa-register по сети — он получает уже собранный клиентский код. Виртуальные модули Vite.

Внутри реализация загружает workbox-window, создаёт Workbox с подготовленным URL и вызывает его регистрацию. Поэтому отдельный чанк workbox-window.prod.es5-….js в Network — ожидаемая часть клиентской загрузки с CDN. Регистратор плагина, подстановка параметров.

Как связаны сборка и регистрация ​

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

Объект workbox при вызове registerSW не передаётся в браузер. Правила уже находятся в коде /sw.js. Регистрация только связывает браузер с этим скриптом и его scope.

Mermaid
mermaid
%% Flowchart: одна конфигурация даёт два результата для разных контекстов.
flowchart TB
  pwaConfig["VitePWA · общая конфигурация"] --> workboxOptions["Настройки workbox"]
  workboxOptions --> workboxBuild["workbox-build · generateSW"]
  workboxBuild --> workerFile["dist/sw.js · правила запросов и precache"]
  pwaConfig --> virtualModule["virtual:pwa-register · URL и scope"]
  virtualModule --> registrationCode["Код registerSW в бандле SPA"]
  workerFile --> publicFile["BFF отдаёт файл по /sw.js"]
  registrationCode --> registrationUrl["SPA регистрирует /sw.js со scope /"]
  classDef build fill:#fed7aa,stroke:#c2410c,color:#374151
  classDef artifact fill:#ddd6fe,stroke:#6d28d9,color:#374151
  class pwaConfig,workboxOptions,workboxBuild,virtualModule build
  class workerFile,registrationCode artifact

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

Где настроен SW в Cellestial ​

В текущем описываемом выпуске конфигурация вынесена из основного Vite-файла в функцию:

ФайлОбязанность
vite.config.prod.tsПодключает общий конфиг и задаёт CDN base выпуска
vite/shared.tsВключает vitepwaPlugin вместе с остальными плагинами
vite/plugins.tsСоздаёт VitePWA с настройками Workbox и манифеста
src/serviceWorker.tsВызывает registerSW из кода страницы
НастройкаГде используетсяКакую задачу решает
workbox.globPatternsСборка SWВыбирает офлайн-страницу для precache; плагин также добавляет публичный манифест
workbox.runtimeCachingГенерирует правила SWНавигация — NetworkOnly, при сетевом отказе — сохранённая офлайн-страница
workbox.inlineWorkboxRuntimeСборка SWВключает используемый runtime Workbox в сам sw.js; это не отменяет отдельную библиотеку страницы
workbox.skipWaiting и workbox.clientsClaimУстановка и активация SWНовая версия не остаётся ждать закрытия всех вкладок и получает управление страницами
injectRegisterПодготовка HTML/клиентаУ нас автоматическая вставка отключена: используется явный вызов из src/serviceWorker.ts
registerSW: immediateСтраницаНачинает регистрацию, не ожидая события загрузки окна; не заменяет активацию SW
registerSW: onNeedReloadСтраницаПустой обработчик предотвращает стандартную перезагрузку плагина и сохраняет ввод
registerSW: onRegisterErrorСтраницаСообщает об ошибке регистрации, не блокируя запуск SPA

Немедленная активация SW и перезагрузка SPA — разные решения. В выбранном режиме SW не кеширует JS/CSS SPA, поэтому смена его версии не требует перезагрузить редактор. Это описание реализации, а не готовый конфиг для копирования в другую архитектуру.

Что выполняется в браузере ​

Код SPA и workbox-window приходят с CDN и исполняются в контексте страницы Cellestial. Браузер получает сам SW с origin приложения, от BFF: https://cellestial.ru/sw.js. Scope равен /; CDN-префикс основного бандла этот адрес не меняет.

Объект регистрации ещё не доказывает успешного precache и управления текущей страницей. Эти факты проверяются отдельно. BFF отдаёт файлы, а регистрацию выполняют код страницы и браузер.

Для обычной разработки bun run dev использует виртуальный модуль-заглушку без регистрации SW. Для локальной проверки готовой сборки есть bun run dev:pwa; устройство команды описано в инструкции frontend. Реализованный офлайн-сценарий, проверенные наблюдения и ограничения — в обзоре; исходная учебная задача — в модуле 2.

Mermaid
mermaid
%% Sequence: регистрация и последующий install/precache — отдельные стадии.
sequenceDiagram
  participant Page as Страница SPA · registerSW
  participant Helper as workbox-window
  participant Browser as Браузер
  participant Public as Публичные файлы BFF
  participant Cache as Cache Storage
  Note over Page,Helper: Клиентский код уже загружен с CDN
  Page->>Helper: Создать Workbox и вызвать register
  Helper->>Browser: Зарегистрировать /sw.js, scope /
  Browser->>Public: GET /sw.js
  Public-->>Browser: Сгенерированный код SW
  Browser->>Browser: Сохранить регистрацию и начать install
  Browser-->>Helper: Объект регистрации
  Note over Browser: SW выполняет install и precache
  Browser->>Public: GET /offline.html и манифест
  Public-->>Browser: Неперсональные публичные файлы
  Browser->>Cache: Сохранить ответы с ревизиями
  Browser->>Browser: Активировать SW и получить управление

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