Работник службы может перехватывать сетевые запросы к странице. Он может отвечать браузеру кэшированным контентом, контентом из сети или контентом, созданным в сервис-воркере.
workbox-routing
— это модуль, который позволяет легко «направлять» эти запросы к различным функциям, которые предоставляют ответы.
Как осуществляется маршрутизация
Когда сетевой запрос вызывает событие выборки сервисного работника, workbox-routing
попытается ответить на запрос, используя предоставленные маршруты и обработчики.
Основные моменты, на которые следует обратить внимание из вышеизложенного:
Важен метод запроса. По умолчанию маршруты регистрируются для запросов
GET
. Если вы хотите перехватывать другие типы запросов, вам необходимо указать метод.Порядок регистрации Маршрута важен. Если зарегистрировано несколько маршрутов, которые могут обрабатывать запрос, для ответа на запрос будет использоваться тот маршрут, который зарегистрирован первым.
Есть несколько способов зарегистрировать маршрут: вы можете использовать обратные вызовы, регулярные выражения или экземпляры Route.
Сопоставление и обработка маршрутов
«Маршрут» в рабочей области — это не что иное, как две функции: функция «сопоставления», определяющая, должен ли маршрут соответствовать запросу, и функция «обработки», которая должна обрабатывать запрос и отвечать ответом.
Workbox поставляется с некоторыми помощниками, которые будут выполнять сопоставление и обработку за вас, но если вам когда-нибудь понадобится другое поведение, лучшим вариантом будет написание собственной функции сопоставления и обработчика.
В функцию обратного вызова match передаются ExtendableEvent
, Request
и объект URL
, который вы можете сопоставить, вернув истинное значение. В качестве простого примера вы можете сопоставить определенный URL-адрес следующим образом:
const matchCb = ({url, request, event}) => {
return url.pathname === '/special/url';
};
Большинство случаев использования можно охватить путем изучения/тестирования либо url
, либо request
.
Функции обратного вызова обработчика будут переданы те же объекты ExtendableEvent
, Request
и URL
, а также значение params
, которое является значением, возвращаемым функцией «match».
const handlerCb = async ({url, request, event, params}) => {
const response = await fetch(request);
const responseBody = await response.text();
return new Response(`${responseBody} <!-- Look Ma. Added Content. -->`, {
headers: response.headers,
});
};
Ваш обработчик должен вернуть обещание, которое разрешается в Response
. В этом примере мы используем async
и await
. Под капотом возвращаемое значение Response
будет заключено в обещание.
Вы можете зарегистрировать эти обратные вызовы следующим образом:
import {registerRoute} from 'workbox-routing';
registerRoute(matchCb, handlerCb);
Единственное ограничение заключается в том, что обратный вызов «match» должен синхронно возвращать истинное значение, вы не можете выполнять какую-либо асинхронную работу. Причина этого в том, что Router
должен синхронно реагировать на событие выборки или разрешать переход к другим событиям выборки.
Обычно обратный вызов «обработчика» использует одну из стратегий, предоставляемых стратегиями рабочего ящика, например:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(matchCb, new StaleWhileRevalidate());
На этой странице мы сосредоточимся на workbox-routing
, но вы можете узнать больше об этих стратегиях на странице Workbox-strategies .
Как зарегистрировать маршрут регулярного выражения
Обычной практикой является использование регулярного выражения вместо обратного вызова «соответствие». Workbox позволяет легко реализовать это следующим образом:
import {registerRoute} from 'workbox-routing';
registerRoute(new RegExp('/styles/.*\\.css'), handlerCb);
Для запросов из одного и того же источника это регулярное выражение будет соответствовать, если URL-адрес запроса соответствует регулярному выражению.
- https://example.com/styles/main.css
- https://example.com/styles/nested/file.css
- https://example.com/nested/styles/directory.css
Однако для запросов из разных источников регулярные выражения должны соответствовать началу URL-адреса . Причина этого в том, что маловероятно, что с помощью регулярного выражения new RegExp('/styles/.*\\.css')
вы намеревались сопоставить сторонние файлы CSS.
- https:// cdn . Third-party-site.com/styles/main.css
- https://cdn . Third-party-site.com/styles/nested/file.css
- https: // cdn. Third-party-site.com/nested/styles/directory.css
Если вам действительно нужно такое поведение, вам просто нужно убедиться, что регулярное выражение соответствует началу URL-адреса. Если бы мы хотели сопоставить запросы https://cdn.third-party-site.com
//cdn. Third-party-site.com, мы могли бы использовать регулярное выражение new RegExp('https://cdn\\.third-party-site\\.com.*/styles/.*\\.css')
.
- https://cdn. Third-party-site.com/styles/main.css
- https://cdn. Third-party-site.com/styles/nested/file.css
- https://cdn. Third-party-site.com/nested/styles/directory.css
Если вы хотите сопоставить как локальные, так и сторонние данные, вы можете использовать подстановочный знак в начале регулярного выражения, но делать это следует с осторожностью, чтобы не вызвать неожиданное поведение в вашем веб-приложении.
Как зарегистрировать навигационный маршрут
Если ваш сайт представляет собой одностраничное приложение, вы можете использовать NavigationRoute
для возврата определенного ответа на все запросы навигации .
import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';
// This assumes /app-shell.html has been precached.
const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler);
registerRoute(navigationRoute);
Всякий раз, когда пользователь заходит на ваш сайт в браузере, запрос страницы будет запросом навигации, и ему будет отправлена кешированная страница /app-shell.html
. (Примечание. Страница должна быть кэширована с помощью workbox-precaching
или на этапе установки самостоятельно.)
По умолчанию это будет отвечать на все запросы навигации. Если вы хотите ограничить его ответом на подмножество URL-адресов, вы можете использовать параметры allowlist
и denylist
чтобы ограничить, какие страницы будут соответствовать этому маршруту.
import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';
// This assumes /app-shell.html has been precached.
const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
allowlist: [new RegExp('/blog/')],
denylist: [new RegExp('/blog/restricted/')],
});
registerRoute(navigationRoute);
Единственное, что следует отметить, это то, что denylist
выиграет, если URL-адрес находится как в списке allowlist
, так и denylist
.
Установить обработчик по умолчанию
Если вы хотите предоставить «обработчик» для запросов, которые не соответствуют маршруту, вы можете установить обработчик по умолчанию.
import {setDefaultHandler} from 'workbox-routing';
setDefaultHandler(({url, event, params}) => {
// ...
});
Установите обработчик захвата
В случае, если какой-либо из ваших маршрутов выдает ошибку, вы можете корректно захватить и ухудшить ситуацию, установив обработчик catch.
import {setCatchHandler} from 'workbox-routing';
setCatchHandler(({url, event, params}) => {
...
});
Определение маршрута для запросов, отличных от GET
По умолчанию предполагается, что все маршруты предназначены для запросов GET
.
Если вы хотите маршрутизировать другие запросы, например POST
запрос, вам необходимо определить метод при регистрации маршрута, например:
import {registerRoute} from 'workbox-routing';
registerRoute(matchCb, handlerCb, 'POST');
registerRoute(new RegExp('/api/.*\\.json'), handlerCb, 'POST');
Протоколирование маршрутизатора
Вы сможете определить поток запроса, используя журналы workbox-routing
, в которых будет указано, какие URL-адреса обрабатываются через Workbox.
Если вам нужна более подробная информация, вы можете установить уровень журнала для debug
, чтобы просматривать журналы запросов, не обрабатываемых маршрутизатором. Дополнительную информацию о настройке уровня журнала см. в нашем руководстве по отладке .
Расширенное использование
Если вы хотите иметь больший контроль над тем, когда маршрутизатор Workbox получает запросы, вы можете создать свой собственный экземпляр Router
и вызывать его метод handleRequest()
всякий раз, когда вы хотите использовать маршрутизатор для ответа на запрос.
import {Router} from 'workbox-routing';
const router = new Router();
self.addEventListener('fetch', event => {
const {request} = event;
const responsePromise = router.handleRequest({
event,
request,
});
if (responsePromise) {
// Router found a route to handle the request.
event.respondWith(responsePromise);
} else {
// No route was found to handle the request.
}
});
При непосредственном использовании Router
вам также потребуется использовать класс Route
или любой из расширяющих классов для регистрации маршрутов.
import {Route, RegExpRoute, NavigationRoute, Router} from 'workbox-routing';
const router = new Router();
router.registerRoute(new Route(matchCb, handlerCb));
router.registerRoute(new RegExpRoute(new RegExp(...), handlerCb));
router.registerRoute(new NavigationRoute(handlerCb));
Типы
NavigationRoute
NavigationRoute упрощает создание workbox-routing.Route
, соответствующего [запросам навигации] браузера https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests
Performance-loading#first_what_are_navigation_requests .
Он будет соответствовать только входящим запросам, для которых https://fetch.spec.whatwg.org/#concept-request-mode|mode
настроен на navigate
.
При желании вы можете применить этот маршрут только к подмножеству запросов навигации, используя один или оба параметра списка denylist
и allowlist
.
Характеристики
пустота
Если указаны и
denylist
, иallowlist
,denylist
будет иметь приоритет, и запрос не будет соответствовать этому маршруту.Регулярные выражения в
allowlist
иdenylist
сопоставляются с объединенными [pathname
]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname
и [search
]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search
частей запрошенного URL-адреса.Примечание . Эти регулярные выражения можно оценивать по каждому целевому URL-адресу во время навигации. Избегайте использования сложных регулярных выражений , иначе ваши пользователи могут столкнуться с задержками при навигации по вашему сайту.
Функция
constructor
выглядит так:(handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}
Функция обратного вызова, которая возвращает обещание, приводящее к ответу.
NavigationRouteMatchOptions необязательно
RouteHandlerObject необязательно
HTTPМетод
пустота
Функция
setCatchHandler
выглядит так:(handler: RouteHandler) => {...}
Функция обратного вызова, которая возвращает обещание, преобразующееся в ответ.
NavigationRouteMatchOptions
Характеристики
RegExp[] необязательно
RegExp[] необязательно
RegExpRoute
RegExpRoute упрощает создание workbox-routing.Route
на основе регулярных выражений.
Для запросов одного и того же происхождения RegExp должен соответствовать только части URL-адреса. Для запросов к сторонним серверам необходимо определить RegExp, соответствующий началу URL-адреса.
Характеристики
- конструктор
пустота
Если регулярное выражение содержит [группы захвата]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references
, захваченные значения будут переданы вworkbox-routing~handlerCallback
аргументparams
.Функция
constructor
выглядит так:(regExp: RegExp, handler: RouteHandler, method?: HTTPMethod) => {...}
- регулярное выражение
Регэксп
Регулярное выражение для сопоставления URL-адресов.
- обработчик
Функция обратного вызова, которая возвращает обещание, приводящее к ответу.
- метод
HTTPMethod необязательно
- возвращает
- catchHandler
RouteHandlerObject необязательно
- обработчик
- соответствовать
- метод
HTTPМетод
- УстановитьCatchHandler
пустота
Функция
setCatchHandler
выглядит так:(handler: RouteHandler) => {...}
- обработчик
Функция обратного вызова, которая возвращает обещание, преобразующееся в ответ.
Route
Route
состоит из пары функций обратного вызова: «match» и «handler». Обратный вызов «match» определяет, следует ли использовать маршрут для «обработки» запроса, возвращая неложное значение, если это возможно. Обратный вызов «обработчика» вызывается при обнаружении совпадения и должен возвращать Promise, который преобразуется в Response
.
Характеристики
- конструктор
пустота
Конструктор класса Route.
Функция
constructor
выглядит так:(match: RouteMatchCallback, handler: RouteHandler, method?: HTTPMethod) => {...}
- соответствовать
Функция обратного вызова, которая определяет, соответствует ли маршрут данному событию
fetch
, возвращая неложное значение. - обработчик
Функция обратного вызова, которая возвращает обещание, преобразующееся в ответ.
- метод
HTTPMethod необязательно
- возвращает
- catchHandler
RouteHandlerObject необязательно
- обработчик
- соответствовать
- метод
HTTPМетод
- УстановитьCatchHandler
пустота
Функция
setCatchHandler
выглядит так:(handler: RouteHandler) => {...}
- обработчик
Функция обратного вызова, которая возвращает обещание, преобразующееся в ответ.
Router
Маршрутизатор можно использовать для обработки FetchEvent
с использованием одного или нескольких workbox-routing.Route
, отвечая Response
, если соответствующий маршрут существует.
Если ни один маршрут не соответствует данному запросу, Маршрутизатор будет использовать обработчик «по умолчанию», если он определен.
Если соответствующий Маршрут выдает ошибку, Маршрутизатор будет использовать обработчик «catch», если он определен для корректного решения проблем и ответа Запросом.
Если запрос соответствует нескольким маршрутам, для ответа на запрос будет использоваться самый ранний зарегистрированный маршрут.
Характеристики
- конструктор
пустота
Инициализирует новый маршрутизатор.
Функция
constructor
выглядит так:() => {...}
- возвращает
- маршруты
Карта<HTTPMethodRoute[]>
- добавитьCacheListener
пустота
Добавляет прослушиватель событий сообщений для кэширования URL-адресов из окна. Это полезно для кэширования ресурсов, загруженных на страницу, до того, как сервис-воркер начал ею управлять.
Формат данных сообщения, отправляемого из окна, должен быть следующим. Где массив
urlsToCache
может состоять из строк URL-адресов или массива строк URL-адресов + объектаrequestInit
(так же, как вы передаете вfetch()
).{ type: 'CACHE_URLS', payload: { urlsToCache: [ './script1.js', './script2.js', ['./script3.js', {mode: 'no-cors'}], ], }, }
Функция
addCacheListener
выглядит так:() => {...}
- добавитьFetchListener
пустота
Добавляет прослушиватель событий выборки для реагирования на события, когда маршрут соответствует запросу события.
Функция
addFetchListener
выглядит так:() => {...}
- findMatchingRoute
пустота
Сверяет запрос и URL-адрес (и, при необходимости, событие) по списку зарегистрированных маршрутов и, если есть совпадение, возвращает соответствующий маршрут вместе со всеми параметрами, сгенерированными в результате совпадения.
Функция
findMatchingRoute
выглядит так:(options: RouteMatchCallbackOptions) => {...}
- параметры
- возвращает
объект
Объект со свойствами
route
иparams
. Они заполняются, если найден соответствующий маршрут, или в противном случаеundefined
.
- handleRequest
пустота
Примените правила маршрутизации к объекту FetchEvent, чтобы получить ответ от соответствующего обработчика маршрута.
Функция
handleRequest
выглядит так:(options: object) => {...}
- параметры
объект
- событие
РасширяемоеСобытие
Событие, вызвавшее запрос.
- запрос
Запрос
Запрос на обработку.
- возвращает
Обещание<Ответ>
Промис возвращается, если зарегистрированный маршрут может обработать запрос. Если соответствующего маршрута нет и нет
defaultHandler
, возвращаетсяundefined
.
- РегистрацияМаршрут
пустота
Регистрирует маршрут на маршрутизаторе.
Функция
registerRoute
выглядит так:(route: Route) => {...}
- маршрут
Маршрут регистрации.
- УстановитьCatchHandler
пустота
Если Route выдает ошибку при обработке запроса, этот
handler
будет вызван и получит возможность предоставить ответ.Функция
setCatchHandler
выглядит так:(handler: RouteHandler) => {...}
- обработчик
Функция обратного вызова, которая возвращает обещание, приводящее к ответу.
- setDefaultHandler
пустота
Определите
handler
по умолчанию, который вызывается, когда ни один маршрут явно не соответствует входящему запросу.Каждый метод HTTP («GET», «POST» и т. д.) получает свой собственный обработчик по умолчанию.
Без обработчика по умолчанию несовпадающие запросы будут отправляться в сеть, как если бы там не было сервисного работника.
Функция
setDefaultHandler
выглядит так:(handler: RouteHandler, method?: HTTPMethod) => {...}
- обработчик
Функция обратного вызова, которая возвращает обещание, приводящее к ответу.
- метод
HTTPMethod необязательно
- отменить регистрациюМаршрут
пустота
Отменяет регистрацию маршрута на маршрутизаторе.
Функция
unregisterRoute
выглядит так:(route: Route) => {...}
- маршрут
Маршрут для отмены регистрации.
Методы
registerRoute()
workbox-routing.registerRoute(
capture: string | RegExp | RouteMatchCallback | Route,
handler?: RouteHandler,
method?: HTTPMethod,
)
Легко зарегистрировать RegExp, строку или функцию с помощью стратегии кэширования в одноэлементном экземпляре Router.
Этот метод при необходимости сгенерирует для вас маршрут и вызовет workbox-routing.Router#registerRoute
.
Параметры
- захватывать
строка | регэксп | МаршрутМатчОбратный вызов | Маршрут
Если параметр захвата —
Route
, все остальные аргументы будут игнорироваться. - обработчик
RouteHandler необязательно
- метод
HTTPMethod необязательно
Возврат
Сгенерированный
Route
.
setCatchHandler()
workbox-routing.setCatchHandler(
handler: RouteHandler,
)
Если Route выдает ошибку при обработке запроса, этот handler
будет вызван и получит возможность предоставить ответ.
Параметры
- обработчик
Функция обратного вызова, которая возвращает обещание, приводящее к ответу.
setDefaultHandler()
workbox-routing.setDefaultHandler(
handler: RouteHandler,
)
Определите handler
по умолчанию, который вызывается, когда ни один маршрут явно не соответствует входящему запросу.
Без обработчика по умолчанию несовпадающие запросы будут отправляться в сеть, как если бы там не было сервисного работника.
Параметры
- обработчик
Функция обратного вызова, которая возвращает обещание, приводящее к ответу.