UX офлайн-режима

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

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

Первым шагом является регистрация сервис-воркера в основном скрипте приложения:

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

Файл sw.js станет точкой управления кэшированием и стратегиями обработки запросов.

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

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

  1. 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 })
        ]
      })
    );
  2. Network First Сначала выполняется сетевой запрос, кэш используется как резерв. Стратегия подходит для динамического контента, где важна актуальность данных:

    import { NetworkFirst } from 'workbox-strategies';
    
    registerRoute(
      ({request}) => request.destination === 'document',
      new NetworkFirst({
        cacheName: 'pages-cache',
        networkTimeoutSeconds: 3
      })
    );
  3. Stale While Revalidate Возвращает кэшированную версию сразу, а сетевой запрос обновляет кэш в фоне. Отлично подходит для ускорения загрузки страниц и снижения задержек:

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

Префетчинг ресурсов (Precache)

Workbox позволяет заранее кэшировать ключевые ресурсы, чтобы обеспечить доступ к ним в офлайн-режиме. Это реализуется через workbox-precaching:

import { precacheAndRoute } from 'workbox-precaching';

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

Примечание: Каждому ресурсу присваивается revision для контроля обновлений кэша. При изменении файла revision необходимо увеличивать.

Обработка ошибок сети

Для обеспечения плавного UX важно обрабатывать ситуации, когда пользователь находится офлайн. Можно создавать fallback-страницы:

registerRoute(
  ({request}) => request.mode === 'navigate',
  async ({event}) => {
    try {
      return await fetch(event.request);
    } catch (error) {
      return caches.match('/offline.html');
    }
  }
);

Такой подход гарантирует, что пользователь увидит информативную страницу даже при отсутствии соединения.

Кэширование API-запросов

Для динамических данных, получаемых через API, Workbox предлагает стратегии с комбинированным подходом. Часто используется NetworkFirst с ограничением времени хранения кэша:

registerRoute(
  ({url}) => url.pathname.startsWith('/api/'),
  new NetworkFirst({
    cacheName: 'api-cache',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 100,
        maxAgeSeconds: 5 * 60 // 5 минут
      })
    ]
  })
);

Такой подход сохраняет свежесть данных при онлайн-доступе и предоставляет доступ к кэшированным результатам при отсутствии сети.

Оптимизация UX при офлайн-доступе

  • Минимизация времени загрузки: использование StaleWhileRevalidate для CSS и JS ускоряет отображение интерфейса.
  • Информирование пользователя: отображение индикатора офлайн-режима повышает доверие и снижает фрустрацию.
  • Контроль объема кэша: ExpirationPlugin предотвращает переполнение хранилища и сбои на устройствах с ограниченной памятью.
  • Адаптивные fallback-ресурсы: использование статических страниц и изображений вместо недоступного контента поддерживает визуальную целостность приложения.

Интеграция с build-системой

Workbox легко интегрируется с Webpack через плагин WorkboxWebpackPlugin. Это позволяет автоматизировать генерацию сервис-воркеров и управление версионированием ресурсов:

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

module.exports = {
  plugins: [
    new GenerateSW({
      clientsClaim: true,
      skipWaiting: true,
      runtimeCaching: [
        {
          urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/,
          handler: 'CacheFirst',
          options: {
            cacheName: 'images',
            expiration: { maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }
          }
        }
      ]
    })
  ]
};

Автоматическая генерация сервис-воркера упрощает поддержку PWA и снижает риск ошибок ручного кэширования.