В современном мире пользователи ожидают, что приложения будут работать, даже если у них нет подключения к Интернету. Создание автономного прогрессивного веб-приложения (PWA) может обеспечить удобство работы пользователей, позволяя им продолжать использовать ваше приложение, даже если они не в сети. В этой статье мы рассмотрим этапы создания автономного PWA с использованием сервис-воркеров и кэширования.

Начало работы. Для начала давайте настроим базовое PWA с манифестом и сервисным работником. Манифест предоставляет метаданные о приложении и позволяет установить его на устройстве пользователя. Service Worker является основой PWA и обеспечивает автономную функциональность.

Сначала создайте файл с именем manifest.json и добавьте следующее содержимое:

{
  "name": "My PWA",
  "short_name": "PWA",
  "theme_color": "#ffffff",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "/images/icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "start_url": "/"
}

Этот манифест включает имя и краткое имя приложения, а также значок и начальный URL-адрес.

Затем создайте файл с именем service-worker.js и добавьте следующее содержимое:

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-cache').then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/script.js',
        '/images/logo.png'
      ]);
    })
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Этот сервисный работник кэширует оболочку приложения (HTML, CSS, JS и изображения), когда пользователь впервые посещает сайт. Затем он перехватывает сетевые запросы и отвечает кэшированным содержимым, когда оно доступно.

Кэширование.Теперь, когда мы настроили базовое PWA с сервис-воркером, давайте реализуем кэширование для обеспечения работы в автономном режиме. Кэширование позволяет нам хранить ресурсы локально на устройстве пользователя, чтобы к ним можно было получить доступ даже при отсутствии подключения к Интернету.

Для реализации кэширования мы будем использовать Cache API. В событии install сервис-воркера мы откроем кеш и добавим в него файлы оболочки нашего приложения:

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-cache').then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/script.js',
        '/images/logo.png'
      ]);
    })
  );
});

Этот код открывает кеш с именем «my-cache» и добавляет в него файлы оболочки приложения. Когда сервис-воркер установлен, эти файлы будут кэшироваться.

Чтобы обслуживать кешированный контент, мы обновим событие fetch сервис-воркера, чтобы проверить кеш на наличие ответа:

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Этот код проверяет кеш на наличие ответа на текущий запрос. Если кэшированный ответ найден, он возвращается. Если нет, запрос перенаправляется в сеть.

Service Workers. Service Worker — важный компонент автономных PWA, поскольку они позволяют нам перехватывать сетевые запросы и предоставлять кешированный контент. Они также позволяют нам обрабатывать аннулирование кеша и обновления.

Для реализации сервис-воркеров мы будем использовать navigator.serviceWorker API в JavaScript. Во-первых, мы зарегистрируем сервис-воркера в нашем основном файле скрипта:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log('Service worker registered:', registration);
      })
      .catch(error => {
        console.log('Service worker registration failed:', error);
      });
  });
}

Этот код проверяет, доступен ли API serviceWorker, и регистрирует работника службы, вызывая navigator.serviceWorker.register(). Мы также можем обрабатывать ошибки, если регистрация не удалась.

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

Аннулирование кеша. Теперь, когда мы внедрили кэширование, нам нужно обработать аннулирование кеша, чтобы гарантировать, что у пользователей всегда будет актуальный контент. Один из способов сделать это — использовать систему управления версиями для файлов оболочки нашего приложения.

Во-первых, мы обновим наш сервис-воркер, чтобы использовать имя кеша, которое включает номер версии:

const cacheName = 'my-cache-v1';

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(cacheName).then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/script.js',
        '/images/logo.png'
      ]);
    })
  );
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys => {
      return Promise.all(keys
        .filter(key => key !== cacheName)
        .map(key => caches.delete(key))
      );
    })
  );
});

Этот код добавляет номер версии к имени кеша и удаляет все старые кеши при активации сервисного работника.

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

Заключение. В этой статье мы рассмотрели этапы создания автономного PWA с использованием сервис-воркеров и кэширования. Мы увидели, как использовать Cache API для локального хранения ресурсов на устройстве пользователя и как использовать сервис-воркеры для перехвата сетевых запросов и предоставления кэшированного контента. Мы также узнали, как обрабатывать аннулирование кэша и обновления с помощью управления версиями.

С помощью этих методов вы можете создавать PWA, которые обеспечивают бесперебойную работу пользователей, даже когда они не в сети.

Удачного кодирования!