工作框路由

Service Worker 可以拦截对页面的网络请求。它可能会响应 缓存内容、来自网络的内容或生成的内容 Service Worker 中的资源。

workbox-routing 是一个模块,可让您轻松地实现“路由”向 提供响应的各种不同函数。

如何执行路由

当网络请求导致 Service Worker 提取事件时,workbox-routing 将使用提供的路由和处理程序响应请求。

工作箱路由图

上述内容需要注意的主要事项包括:

  • 请求的方法很重要。默认情况下,系统会为 GET 请求。如果您希望拦截其他类型的请求,则需要 以指定方法。

  • 路由注册的顺序很重要。如果有多个路由 可以处理请求的 Route,最先注册的 Route 将用于响应请求。

注册路线有几种方法:您可以使用回调、常规的 表达式或路由实例。

路由中的匹配和处理

“路线”只不过是两个函数:“匹配”函数 以确定路线是否与请求和“订单处理”相匹配函数, 它应处理请求并给出响应

Workbox 附带一些帮助程序,可用于对 但是,如果您发现自己想要不同的行为, 自定义匹配和处理程序函数是最佳选择。

匹配回调函数 传递一个 ExtendableEventRequestURL对象 匹配。举一个简单的例子,您可以匹配 具体网址,例如:

const matchCb = ({url, request, event}) => {
  return url.pathname === '/special/url';
};

大多数用例都可以通过检查 / 测试 urlrequest

handler 回调函数 将获得 ExtendableEventRequestURL 对象以及 一个 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 的 promise。在本课中, 我们使用的是 asyncawait。 在后台,返回的 Response 值会封装在 promise 中。

您可以按如下方式注册这些回调:

import {registerRoute} from 'workbox-routing';

registerRoute(matchCb, handlerCb);

唯一的限制是,“匹配”回调必须同步返回一个 True 值,就无法执行任何异步工作。原因就在于 Router 必须同步响应提取事件或允许掉落 直到出现其他提取事件

通常,“处理程序”回调将使用所提供的策略之一 按workbox-strategies,如下所示:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

registerRoute(matchCb, new StaleWhileRevalidate());

在本页中,我们将重点介绍workbox-routing详细了解工作箱策略方面的这些策略

如何注册正则表达式路由

常见做法是使用正则表达式,而不是“匹配”回调。 借助 Workbox,可轻松实现,如下所示:

import {registerRoute} from 'workbox-routing';

registerRoute(new RegExp('/styles/.*\\.css'), handlerCb);

对于来自 同源, 那么,只要请求的网址与 正则表达式。

  • https://example.com/styles/main.css
  • https://example.com/styles/nested/file.css
  • https://example.com/nested/styles/directory.css

不过,对于跨源请求,正则表达式 必须与网址的开头保持一致。其原因在于, 使用正则表达式 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

如果您确实需要这种行为,只需确保常规 匹配网址的开头。如果我们想将 请求 https://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

如果您想同时匹配本地和第三方,可以使用通配符 放在正则表达式的开头,但在使用时应格外小心 以确保它不会导致您的 Web 应用出现意外行为。

如何注册导航路线

如果您的网站是单页应用,您可以使用 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 或通过 自行安装步骤。)

默认情况下,这将响应所有导航请求。如果您想 限制它仅响应一部分网址,您可以使用 allowlistdenylist 选项,用于限制哪些页面与此路由匹配。

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 将胜出 allowlistdenylist

设置默认处理程序

如果您想提供一个“处理程序”对于与路由不匹配的请求 可以设置默认处理程序

import {setDefaultHandler} from 'workbox-routing';

setDefaultHandler(({url, event, params}) => {
  // ...
});

设置 Catch 处理程序

如果您的任何路由引发错误,您可以捕获并 通过设置 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,突出显示正在处理的网址 自动同步。

路由日志

如果您需要更详细的信息,可以将日志级别设置为 debug, 查看未由路由器处理的请求的日志。请参阅我们的 调试指南,详细了解 设置日志级别

调试和记录路由消息

高级用法

想要更好地控制何时为 Workbox Router 提供 您可以创建自己的 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

它只会匹配符合以下条件的传入请求: https://fetch.spec.whatwg.org/#concept-request-mode|mode 设为 navigate

您可以选择仅将此路线应用于部分导航请求 使用 denylist 和/或 allowlist 参数。

属性

  • 构造函数

    void

    如果同时提供了 denylistallowlistdenylist 将 且相应请求与此路由不匹配。

    allowlistdenylist 中的正则表达式 与串联的 [pathname]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname 和 [search]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search 部分。

    注意:在运行实验的过程中,系统可能会针对每个目标网址评估这些正则表达式 导航。避免使用 复杂的正则表达式, 否则用户在浏览您的网站时可能会遇到延迟

    constructor 函数如下所示:

    (handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}

  • catchHandler
  • method

    HTTPMethod

  • setCatchHandler

    void

    setCatchHandler 函数如下所示:

    (handler: RouteHandler) => {...}

    • handler

      回调 用于返回解析为 Response 的 Promise 的函数

NavigationRouteMatchOptions

属性

  • 许可名单

    RegExp[] 可选

  • 拒绝名单

    RegExp[] 可选

RegExpRoute

RegExpRoute 可让您轻松创建基于 workbox-routing.Route

对于同源请求,正则表达式只需要匹配网址的一部分。对于 针对第三方服务器发送请求,您必须定义一个与 网址的开头。

属性

  • 构造函数

    void

    如果正则表达式包含 [捕获组]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) => {...}

    • regExp

      RegExp

      要与网址匹配的正则表达式。

    • handler

      回调 函数,该函数会返回 Promise 并产生 Response。

    • method

      HTTPMethod(可选)

  • catchHandler
  • method

    HTTPMethod

  • setCatchHandler

    void

    setCatchHandler 函数如下所示:

    (handler: RouteHandler) => {...}

    • handler

      回调 用于返回解析为 Response 的 Promise 的函数

Route

Route 由一对回调函数“match”组成和“handler”。 “匹配”回调来确定是否应将路线用于“处理”一 通过返回一个非 Falsy 值(如果可以)请求。“处理程序”回拨 如果存在匹配项,则调用该 promise,并且应返回一个可解析的 promise 转换为 Response

属性

  • 构造函数

    void

    Route 类的构造函数。

    constructor 函数如下所示:

    (match: RouteMatchCallback, handler: RouteHandler, method?: HTTPMethod) => {...}

    • 一个回调函数,用于确定路线是否与指定的 通过返回非 falsy 值来触发 fetch 事件。

    • handler

      回调 函数,该函数返回解析为 Response 的 Promise。

    • method

      HTTPMethod(可选)

  • catchHandler
  • method

    HTTPMethod

  • setCatchHandler

    void

    setCatchHandler 函数如下所示:

    (handler: RouteHandler) => {...}

    • handler

      回调 用于返回解析为 Response 的 Promise 的函数

Router

该路由器可以用来处理FetchEvent使用一个或多个 workbox-routing.Route,如果满足以下条件,则返回 Response: 存在匹配的路由。

如果没有与给定请求匹配的路由,路由器将使用“default” 处理程序。

如果匹配的路由抛出错误,路由器将使用“catch” 处理程序(如果定义了一个处理程序,以优雅地处理问题并使用 请求。

如果某个请求与多个路由匹配,则最早的注册路由将 用于响应请求。

属性

  • 构造函数

    void

    初始化新的路由器。

    constructor 函数如下所示:

    () => {...}

  • 路由

    Map&lt;HTTPMethodRoute[]&gt;

  • addCacheListener

    void

    为要从窗口中缓存的网址添加消息事件监听器。 这对于在调用 Service Worker 开始控制它。

    从窗口发送的消息数据的格式应如下所示。 其中 urlsToCache 数组可以由网址字符串或 网址字符串 + requestInit 对象(与传递给 fetch() 的对象相同)。

    {
      type: 'CACHE_URLS',
      payload: {
        urlsToCache: [
          './script1.js',
          './script2.js',
          ['./script3.js', {mode: 'no-cors'}],
        ],
      },
    }
    

    addCacheListener 函数如下所示:

    () => {...}

  • addFetchListener

    void

    添加了提取事件监听器,以便在路由匹配时响应事件 事件请求后返回的值。

    addFetchListener 函数如下所示:

    () => {...}

  • findMatchingRoute

    void

    根据列表检查请求和网址(以及事件) 注册路由,如果有匹配项,则返回 以及由匹配结果生成的所有参数。

    findMatchingRoute 函数如下所示:

    (options: RouteMatchCallbackOptions) => {...}

    • 返回

      对象

      一个具有 routeparams 属性的对象。 如果找到了匹配的路由或 undefined,则会填充这些字段 否则。

  • handleRequest

    void

    将路由规则应用于 FetchEvent 对象,以从 相应 Route 的处理程序。

    handleRequest 函数如下所示:

    (options: object) => {...}

    • 选项

      对象

      • 事件

        ExtendableEvent

        触发 请求。

      • request

        请求

        要处理的请求。

    • 返回

      Promise&lt;Response&gt;

      如果 就可以处理该请求如果没有匹配的 路线,并且没有 defaultHandler,则返回 undefined

  • registerRoute

    void

    向路由器注册路由。

    registerRoute 函数如下所示:

    (route: Route) => {...}

    • 路线

      要注册的路线。

  • setCatchHandler

    void

    如果 Route 在处理请求时抛出错误,此 handler 将调用 ,并有机会给出响应。

    setCatchHandler 函数如下所示:

    (handler: RouteHandler) => {...}

    • handler

      回调 函数,该函数返回 Promise 并产生 Response。

  • setDefaultHandler

    void

    定义在没有显式路由时调用的默认 handler 与传入请求匹配。

    每个 HTTP 方法(“GET”、“POST”等)都有自己的默认处理程序。

    如果没有默认处理程序,不匹配的请求将处理 就像没有 Service Worker 一样。

    setDefaultHandler 函数如下所示:

    (handler: RouteHandler, method?: HTTPMethod) => {...}

    • handler

      回调 函数,该函数返回 Promise 并产生 Response。

    • method

      HTTPMethod(可选)

  • unregisterRoute

    void

    向路由器取消注册路由。

    unregisterRoute 函数如下所示:

    (route: Route) => {...}

    • 路线

      要取消注册的路由。

方法

registerRoute()

workbox-routing.registerRoute(
  capture: string | RegExp | RouteMatchCallback | Route,
  handler?: RouteHandler,
  method?: HTTPMethod,
)

使用缓存轻松注册正则表达式、字符串或函数 单例路由器实例。

此方法会为您生成一个 Route(如果需要),并且 调用 workbox-routing.Router#registerRoute

参数

  • 截图/录像

    string |正则表达式 |RouteMatchCallback |路线

    如果捕获参数为 Route,则将忽略所有其他参数。

  • handler

    RouteHandler(可选)

  • method

    HTTPMethod(可选)

返回

setCatchHandler()

workbox-routing.setCatchHandler(
  handler: RouteHandler,
)

如果 Route 在处理请求时抛出错误,此 handler 将调用 ,并有机会给出响应。

参数

  • handler

    回调 函数,该函数会返回 Promise 并产生 Response。

setDefaultHandler()

workbox-routing.setDefaultHandler(
  handler: RouteHandler,
)

定义在没有显式路由时调用的默认 handler 与传入请求匹配。

如果没有默认处理程序,不匹配的请求将处理 就像没有 Service Worker 一样。

参数

  • handler

    回调 函数,该函数会返回 Promise 并产生 Response。