Переход с Workbox v5 на v6

В этом руководстве рассматриваются критические изменения, представленные в Workbox v6, с примерами изменений, которые вам необходимо внести при обновлении с Workbox v5.

Критические изменения

workbox-core

Метод skipWaiting() в workbox-core больше не будет добавлять обработчик install и будет эквивалентен вызову self.skipWaiting().

Вместо него используйте self.skipWaiting(), поскольку skipWaiting(), скорее всего, будет удален в Workbox версии 7.

workbox-precaching

  • HTML-документы из разных источников для URL, которые соответствуют HTTP-переадресации, больше нельзя использовать для выполнения запроса навигации с помощью workbox-precaching. Такой сценарий встречается редко.
  • Теперь workbox-precaching игнорирует параметр запроса URL fbclid при поиске предварительно кешированного ответа на заданный запрос.
  • Конструктор PrecacheController теперь принимает в качестве параметра объект с определенными свойствами, а не строку. Этот объект поддерживает следующие свойства: cacheName (выполняет ту же функцию, что и строка, переданная конструктору в версии 5), plugins (заменяет метод addPlugins() из версии 5) и fallbackToNetwork (заменяет аналогичный параметр, переданный createHandler() и createHandlerBoundToURL() в версии 5).
  • Методы install() и activate() класса PrecacheController теперь принимают ровно один параметр, который должен быть задан как InstallEvent или ActivateEvent соответственно.
  • Из класса PrecacheController удален метод addRoute(). Вместо него для создания маршрута, который затем можно зарегистрировать, используется новый класс PrecacheRoute.
  • Из класса PrecacheController удален метод precacheAndRoute(). (Он по-прежнему существует как статический вспомогательный метод, экспортируемый модулем workbox-precaching.) Оно было удалено, поскольку вместо него можно использовать PrecacheRoute.
  • Из класса PrecacheController удален метод createMatchCalback(). Вместо него можно использовать новый метод PrecacheRoute.
  • Из класса PrecacheController удален метод createHandler(). Вместо этого для обработки запросов можно использовать свойство strategy объекта PrecacheController.
  • Статический экспорт createHandler() уже удален из модуля workbox-precaching. Вместо этого разработчикам следует создать экземпляр PrecacheController и использовать его свойство strategy.
  • Маршрут, зарегистрированный с помощью precacheAndRoute(), теперь является "настоящим" маршрутом, который использует класс Router из workbox-routing. Это может привести к другому порядку оценки маршрутов, если вы чередуете вызовы registerRoute() и precacheAndRoute().

workbox-routing

Метод setDefaultHandler() теперь принимает необязательный второй параметр, соответствующий методу HTTP, к которому он применяется. По умолчанию используется 'GET'.

  • Если вы используете setDefaultHandler() и все ваши запросы – GET, то никаких изменений вносить не нужно.
  • Если у вас есть запросы, которые не являются GET (POST, PUT и т. д.), setDefaultHandler() больше не будет вызывать совпадение этих запросов.

Конфигурация сборки

Параметр mode для режимов getManifest и injectManifest в workbox-build и workbox-cli не поддерживается и был удален. Это не относится к workbox-webpack-plugin, который поддерживает mode в плагине InjectManifest.

Для инструментов сборки требуется Node.js версии 10 или выше

Версии Node.js до 10 больше не поддерживаются для workbox-webpack-plugin, workbox-build и workbox-cli. Если вы используете версию Node.js ниже 8, обновите среду выполнения до поддерживаемой версии.

Новые улучшения

workbox-strategies

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

Новый базовый класс Strategy

В версии 6 все классы стратегий Workbox должны расширять новый базовый класс Strategy. Все встроенные стратегии были переписаны для поддержки этого.

Базовый класс Strategy отвечает за две основные задачи:

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

Новый класс обработчика

Раньше у нас были внутренние модули fetchWrapper и cacheWrapper, которые, как понятно из названия, оборачивают различные API для получения и кеширования данных с хуками в их жизненном цикле. Это механизм, который в настоящее время позволяет плагинам работать, но он не доступен разработчикам.

Новый класс обработчика StrategyHandler будет предоставлять эти методы, чтобы пользовательские стратегии могли вызывать fetch() или cacheMatch() и автоматически вызывать любые плагины, добавленные в экземпляр стратегии.

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

Новый статус жизненного цикла плагина

В Workbox версии 5 плагины не сохраняют состояние. Это означает, что если запрос /index.html активирует обратные вызовы requestWillFetch и cachedResponseWillBeUsed, то они не смогут обмениваться данными и даже не будут знать, что их активировал один и тот же запрос.

В версии 6 всем обратным вызовам плагина также будет передаваться новый объект state. Этот объект состояния будет уникальным для этого конкретного объекта плагина и этого конкретного вызова стратегии (т. е. вызова handle()). Это позволяет разработчикам писать плагины, в которых один обратный вызов может условно делать что-то на основе того, что сделал другой обратный вызов в том же плагине (например, вычислять разницу во времени между запуском requestWillFetch и fetchDidSucceed или fetchDidFail).

Новые обратные вызовы жизненного цикла плагина

Добавлены новые обратные вызовы жизненного цикла плагина, чтобы разработчики могли полностью использовать его состояние:

  • handlerWillStart – вызывается до запуска логики обработчика. Этот обратный вызов можно использовать, чтобы задать начальное состояние обработчика (например, записать время начала).
  • handlerWillRespond: вызывается до того, как метод strategies handle() возвращает ответ. Этот обратный вызов можно использовать для изменения ответа перед его возвратом обработчику маршрута или другой пользовательской логике.
  • handlerDidRespond: вызывается после того, как метод handle() стратегии возвращает ответ. Этот обратный вызов можно использовать для записи любых сведений об окончательном ответе, например после изменений, внесенных другими плагинами.
  • handlerDidComplete: вызывается после того, как все промисы продления времени жизни, добавленные в событие в результате вызова этой стратегии, будут выполнены. Этот обратный вызов можно использовать для создания отчетов по любым данным, которые необходимо рассчитать после завершения работы обработчика (например, статус совпадения в кеше, задержка кеша, задержка сети).
  • handlerDidError: вызывается, если обработчик не смог предоставить действительный ответ ни из одного источника. Этот обратный вызов можно использовать для предоставления резервного контента в качестве альтернативы ошибке сети.

Разработчикам, реализующим собственные стратегии, не нужно беспокоиться о вызове этих обратных вызовов самостоятельно. Все это обрабатывается новым базовым классом Strategy.

Более точные типы TypeScript для обработчиков.

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

workbox-window

Новый метод messageSkipWaiting()

В модуль workbox-window добавлен новый метод messageSkipWaiting(), который упрощает активацию ожидающего сервис-воркера. Это дает следующие преимущества:

  • Он вызывает postMessage() с де-факто стандартным текстом сообщения {type: 'SKIP_WAITING'}, который проверяет сервис-воркер, созданный Workbox, чтобы запустить skipWaiting().
  • Он выбирает правильный "ожидающий" сервис-воркер, чтобы отправить ему это сообщение, даже если это не тот сервис-воркер, с которым был зарегистрирован workbox-window.

Удаление "внешних" событий в пользу свойства isExternal

Все внешние события в workbox-window были удалены и заменены обычными событиями со свойством isExternal, для которого задано значение true. Это позволяет разработчикам, которым важно различать эти два случая, по-прежнему делать это, а тем, кому это не нужно, – игнорировать свойство.

Более простой рецепт "Предложение пользователям перезагрузить страницу"

Благодаря этим изменениям рецепт Предложение перезагрузить страницу можно упростить:

// v6:
<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.0.0-alpha.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');

    const showSkipWaitingPrompt = () => {
      // This assumes a hypothetical createUIPrompt() method with
      // onAccept and onReject callbacks:
      const prompt = createUIPrompt({
        onAccept: () => {
          wb.addEventListener('controlling', () => {
            window.location.reload();
          });

          // This will postMessage() to the waiting service worker.
          wb.messageSkipWaiting();
        },

        onReject: () => {
          prompt.dismiss();
        },
      });
    };

    // Listening for externalwaiting is no longer needed.
    wb.addEventListener('waiting', showSkipWaitingPrompt);
    wb.register();
  }
</script>

workbox-routing

Новый логический параметр sameOrigin передается в функцию matchCallback, которая используется в workbox-routing. Если запрос предназначен для URL того же источника, используется значение true, в противном случае – false.

Это упрощает некоторые распространенные шаблоны:

// In v5:
registerRoute(
  ({url}) =>
    url.origin === self.location.origin && url.pathname.endsWith('.png'),
  new StaleWhileRevalidate({cacheName: 'local-png'})
);

// In v6:
registerRoute(
  ({sameOrigin, url}) => sameOrigin && url.pathname.endsWith('.png'),
  new StaleWhileRevalidate({cacheName: 'local-png'})
);

matchOptions в workbox-expiration

Теперь вы можете задать matchOptions в workbox-expiration, и это значение будет передано в качестве CacheQueryOptions в базовый вызов cache.delete(). (Большинству разработчиков это не требуется.)

workbox-precaching

Использует workbox-strategies

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

Теперь предварительное кеширование обрабатывает записи по одной, а не все сразу.

workbox-precaching был обновлен, чтобы запрашивать и кэшировать только одну запись в манифесте предварительного кэширования за раз, вместо того, чтобы пытаться запросить и кэшировать их все сразу (оставляя браузеру решать, как регулировать).

Это должно снизить вероятность ошибок net::ERR_INSUFFICIENT_RESOURCES при предварительном кешировании, а также уменьшить конкуренцию за пропускную способность между предварительным кешированием и одновременными запросами, выполняемыми веб-приложением.

PrecacheFallbackPlugin упрощает резервное копирование в офлайн-режиме

В workbox-precaching теперь есть PrecacheFallbackPlugin, в котором реализован новый метод жизненного цикла handlerDidError, добавленный в версии 6.

Это позволяет легко указать предварительно кэшированный URL-адрес в качестве «резервного» для данной стратегии, когда ответ в противном случае был бы недоступен. Плагин правильно создаст ключ кеша для URL предварительно кешированного ресурса, включая все необходимые параметры версии.

Вот пример того, как использовать его для ответа с предварительно кэшированным /offline.html, когда стратегия NetworkOnly не может сгенерировать ответ на запрос навигации – другими словами, отобразить настраиваемую автономную HTML-страницу:

import {PrecacheFallbackPlugin, precacheAndRoute} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

// Ensure that /offline.html is part of your precache manifest!
precacheAndRoute(self.__WB_MANIFEST);

registerRoute(
  ({request}) => request.mode === 'navigate',
  new NetworkOnly({
    plugins: [
      new PrecacheFallbackPlugin({
        fallbackURL: '/offline.html',
      }),
    ],
  })
);

precacheFallback в кешировании во время выполнения

Если вы используете generateSW для создания сервис-воркера, а не пишете его вручную, то можете использовать новый параметр конфигурации precacheFallback в runtimeCaching, чтобы добиться того же результата:

{
  // ... other generateSW config options...
  runtimeCaching: [{
    urlPattern: ({request}) => request.mode === 'navigate',
    handler: 'NetworkOnly',
    options: {
      precacheFallback: {
        // This URL needs to be included in your precache manifest.
        fallbackURL: '/offline.html',
      },
    },
  }],
}

Если вам нужна помощь

Мы ожидаем, что в большинстве случаев перенос будет простым. Если вы столкнулись с проблемой, которая не описана в этом руководстве, сообщите о ней на GitHub.