Workbox и Create React App

Create React App (CRA) по умолчанию предоставляет базовую поддержку Service Worker через пакет workbox-webpack-plugin. Для более тонкой настройки кеширования и стратегии обновления необходимо расширять конфигурацию Webpack или использовать cra-template-pwa при создании проекта.

npx create-react-app my-app --template cra-template-pwa

Эта команда создаёт проект с уже включённой поддержкой Service Worker, который управляется Workbox. При сборке приложения npm run build генерирует файл service-worker.js в директории build, где прописаны базовые правила кеширования.


Основные концепции Workbox

1. Стратегии кеширования (Caching Strategies) Workbox предоставляет несколько готовых стратегий, которые определяют, как обрабатываются сетевые запросы:

  • Cache First: сначала ищет ресурс в кеше, если нет — запрашивает с сервера.
  • Network First: сначала пытается получить ресурс с сервера, при неудаче использует кеш.
  • Stale While Revalidate: возвращает кешированный ресурс, но параллельно обновляет кеш с сервера.
  • Network Only и Cache Only: используются для полной зависимости от сети или полностью локального кеша.

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

import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';

registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images-cache',
    plugins: [
      new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 30 * 24 * 60 * 60 }),
    ],
  })
);

Кеширование статических ресурсов CRA

CRA генерирует в папке build/static JS и CSS файлы с хэшами в названиях. Для них подходит стратегия Cache First, так как изменения версии файла ведут к обновлению кеша автоматически:

registerRoute(
  ({ url }) => url.pathname.startsWith('/static/'),
  new CacheFirst({
    cacheName: 'static-resources',
  })
);

Обработка API-запросов

Для данных, которые часто обновляются, лучше использовать Network First или Stale While Revalidate:

registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new NetworkFirst({
    cacheName: 'api-cache',
    networkTimeoutSeconds: 5,
    plugins: [
      new ExpirationPlugin({ maxEntries: 100, maxAgeSeconds: 5 * 60 }),
    ],
  })
);
  • networkTimeoutSeconds позволяет возвращать кешированный ответ, если сервер не отвечает вовремя.
  • maxAgeSeconds ограничивает срок хранения данных.

Предварительное кеширование ресурсов (Precache)

Workbox поддерживает механизм предварительного кеширования, который гарантирует доступность критичных ресурсов офлайн. CRA автоматически использует precacheAndRoute для статических файлов сборки:

import { precacheAndRoute } from 'workbox-precaching';

precacheAndRoute(self.__WB_MANIFEST);
  • self.__WB_MANIFEST — массив файлов, сгенерированных на этапе сборки.
  • Все файлы, указанные в манифесте, будут доступны офлайн сразу после установки Service Worker.

Работа с событиями Service Worker

Workbox упрощает обработку событий, таких как install, activate и message.

Пример обновления Service Worker при новом билде:

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

В приложении можно отправить сообщение:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.ready.then((registration) => {
    registration.waiting?.postMessage({ type: 'SKIP_WAITING' });
  });
}

Это позволяет мгновенно активировать новый SW и обновить приложение без перезагрузки страницы пользователем.


Кеширование динамических страниц и маршрутов

Для SPA на React важно кешировать HTML и маршруты правильно. Используется комбинация стратегий:

registerRoute(
  ({ request }) => request.mode === 'navigate',
  new NetworkFirst({
    cacheName: 'html-cache',
    plugins: [
      new ExpirationPlugin({ maxEntries: 20 }),
    ],
  })
);
  • request.mode === 'navigate' выбирает запросы на навигацию (страницы).
  • Network First обеспечивает актуальность контента, при недоступности сети используется кеш.

Расширенные возможности Workbox

  1. Background Sync Позволяет отложенно отправлять запросы на сервер при восстановлении сети:
import { BackgroundSyncPlugin } from 'workbox-background-sync';

const bgSyncPlugin = new BackgroundSyncPlugin('queueName', {
  maxRetentionTime: 24 * 60, // в минутах
});

registerRoute(
  /\/api\/submit/,
  new NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
  'POST'
);
  1. Routing и Custom Handlers Можно создавать собственные обработчики запросов для уникальных сценариев:
import { registerRoute } from 'workbox-routing';

registerRoute(
  ({ url }) => url.pathname.startsWith('/special/'),
  async ({ request }) => {
    const response = await fetch(request);
    return response;
  }
);
  1. Фильтрация по типу ресурсов Workbox позволяет создавать маршруты, фильтруя по destination, method, url или другим свойствам.

Настройка сборки CRA для Workbox

По умолчанию CRA скрывает конфигурацию Webpack. Для полной кастомизации Service Worker можно использовать craco или react-app-rewired:

// craco.config.js
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

module.exports = {
  webpack: {
    plugins: [
      new WorkboxWebpackPlugin.InjectManifest({
        swSrc: './src/custom-service-worker.js',
      }),
    ],
  },
};
  • InjectManifest позволяет использовать собственный файл Service Worker, сохраняя преимущества Workbox, такие как precache и стратегии кеширования.

Workbox совместно с CRA обеспечивает гибкую и мощную систему кеширования, офлайн-доступности и обновления приложений. Стратегии кеширования, предварительное кеширование, Background Sync и расширенные возможности маршрутизации позволяют создавать прогрессивные веб-приложения, полностью интегрированные с современными практиками разработки React.