Workbox в одностраничных приложениях

Workbox — это мощная библиотека для упрощения работы с сервис-воркерами в JavaScript. Она позволяет эффективно кэшировать ресурсы, оптимизировать загрузку и улучшать оффлайн-поддержку одностраничных приложений (SPA). В SPA ключевой задачей является обеспечение быстрой загрузки контента при повторных посещениях и корректная работа приложения при отсутствии сети.

Регистрация сервис-воркера

Сервис-воркер регистрируется в основном файле приложения, например index.js:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('Service Worker зарегистрирован с областью:', registration.scope);
    })
    .catch(error => {
      console.error('Ошибка регистрации Service Worker:', error);
    });
}

Регистрация сервис-воркера создаёт основу для работы всех стратегий кэширования, предоставляемых Workbox.

Основные модули Workbox

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

  • workbox-precaching — управление статическими ресурсами приложения, позволяя кэшировать их на этапе сборки.
  • workbox-routing — маршрутизация запросов через сервис-воркер, перенаправление сетевых запросов на кэш или сеть.
  • workbox-strategies — определение стратегий кэширования, таких как CacheFirst, NetworkFirst, StaleWhileRevalidate.
  • workbox-expiration — управление сроком жизни кэша и количеством хранимых элементов.
  • workbox-background-sync — поддержка фоновой синхронизации данных при восстановлении сети.

Прекэширование ресурсов

Прекэширование — это сохранение статических ресурсов ещё до их запроса пользователем. Workbox позволяет автоматически генерировать список ресурсов на этапе сборки с помощью плагина в Webpack или через CLI. Пример конфигурации в sw.js:

import { precacheAndRoute } from 'workbox-precaching';

precacheAndRoute([
  { url: '/index.html', revision: '123456' },
  { url: '/styles/main.css', revision: '123456' },
  { url: '/scripts/app.js', revision: '123456' },
]);

Ключевой момент — использование revision, чтобы Workbox отслеживал изменения файлов и обновлял кэш при необходимости.

Стратегии кэширования

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, // 30 дней
      }),
    ],
  })
);

Network First

Подходит для динамических данных, таких как API-запросы:

import { NetworkFirst } from 'workbox-strategies';

registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new NetworkFirst({
    cacheName: 'api-cache',
    networkTimeoutSeconds: 5,
  })
);

Stale While Revalidate

Сочетает преимущества кэша и сети, предоставляя быстрый отклик из кэша и обновляя его фоново:

import { StaleWhileRevalidate } from 'workbox-strategies';

registerRoute(
  ({ request }) => request.destination === 'script' || request.destination === 'style',
  new StaleWhileRevalidate({
    cacheName: 'static-resources',
  })
);

Фоновые задачи и синхронизация

Workbox поддерживает фоновые операции через модуль workbox-background-sync. Это позволяет сохранять действия пользователя локально при отсутствии сети и отправлять их на сервер, когда соединение восстановлено:

import { Queue } from 'workbox-background-sync';

const queue = new Queue('apiQueue');

self.addEventListener('fetch', event => {
  if (event.request.method === 'POST') {
    event.respondWith(
      fetch(event.request).catch(() => {
        return queue.pushRequest({ request: event.request });
      })
    );
  }
});

Управление жизненным циклом кэша

Workbox позволяет контролировать размер кэша и срок хранения:

  • maxEntries — максимальное количество объектов в кэше.
  • maxAgeSeconds — максимальное время хранения ресурса.
  • purgeOnQuotaError — автоматическая очистка при нехватке места.

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

Интеграция с сборщиками

Workbox легко интегрируется с Webpack и Vite. Плагин Workbox Webpack Plugin позволяет генерировать сервис-воркер автоматически на этапе сборки, включая список всех статических ресурсов. Пример настройки в webpack.config.js:

const { GenerateSW } = require('workbox-webpack-plugin');

module.exports = {
  // ...другие настройки Webpack
  plugins: [
    new GenerateSW({
      clientsClaim: true,
      skipWaiting: true,
      runtimeCaching: [
        {
          urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
          handler: 'CacheFirst',
          options: {
            cacheName: 'images-cache',
            expiration: {
              maxEntries: 60,
              maxAgeSeconds: 30 * 24 * 60 * 60,
            },
          },
        },
      ],
    }),
  ],
};

Практические советы

  • Использовать CacheFirst для редко меняющихся ресурсов и NetworkFirst для динамических данных.
  • Применять StaleWhileRevalidate для скриптов и стилей, чтобы ускорить повторную загрузку.
  • Настраивать ревизию файлов для безопасного обновления кэша.
  • Следить за размерами кэшей и сроками хранения, особенно при работе с большим количеством изображений и данных.

Workbox обеспечивает надёжное и гибкое управление ресурсами SPA, улучшая производительность, снижая время загрузки и поддерживая оффлайн-работу без сложной ручной настройки сервис-воркеров.