Service Worker 可以拦截对页面的网络请求。它可能会响应 缓存内容、来自网络的内容或生成的内容 Service Worker 中的资源。
workbox-routing
是一个模块,可让您轻松地实现“路由”向
提供响应的各种不同函数。
如何执行路由
当网络请求导致 Service Worker 提取事件时,workbox-routing
将使用提供的路由和处理程序响应请求。
上述内容需要注意的主要事项包括:
请求的方法很重要。默认情况下,系统会为
GET
请求。如果您希望拦截其他类型的请求,则需要 以指定方法。路由注册的顺序很重要。如果有多个路由 可以处理请求的 Route,最先注册的 Route 将用于响应请求。
注册路线有几种方法:您可以使用回调、常规的 表达式或路由实例。
路由中的匹配和处理
“路线”只不过是两个函数:“匹配”函数 以确定路线是否与请求和“订单处理”相匹配函数, 它应处理请求并给出响应
Workbox 附带一些帮助程序,可用于对 但是,如果您发现自己想要不同的行为, 自定义匹配和处理程序函数是最佳选择。
答
匹配回调函数
传递一个
ExtendableEvent
、
Request
和
URL
对象
匹配。举一个简单的例子,您可以匹配
具体网址,例如:
const matchCb = ({url, request, event}) => {
return url.pathname === '/special/url';
};
大多数用例都可以通过检查 / 测试 url
或
request
。
答
handler 回调函数
将获得
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
的 promise。在本课中,
我们使用的是
async
和 await
。
在后台,返回的 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
或通过
自行安装步骤。)
默认情况下,这将响应所有导航请求。如果您想
限制它仅响应一部分网址,您可以使用 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
将胜出
allowlist
和 denylist
。
设置默认处理程序
如果您想提供一个“处理程序”对于与路由不匹配的请求 可以设置默认处理程序
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
如果同时提供了
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
部分。注意:在运行实验的过程中,系统可能会针对每个目标网址评估这些正则表达式 导航。避免使用 复杂的正则表达式, 否则用户在浏览您的网站时可能会遇到延迟
constructor
函数如下所示:(handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}
-
回调 函数,该函数会返回 Promise 并产生 Response。
-
-
HTTPMethod
-
void
setCatchHandler
函数如下所示:(handler: RouteHandler) => {...}
-
回调 用于返回解析为 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
-
handler
-
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
-
handler
-
method
HTTPMethod
-
setCatchHandler
void
setCatchHandler
函数如下所示:(handler: RouteHandler) => {...}
-
handler
回调 用于返回解析为 Response 的 Promise 的函数
-
Router
该路由器可以用来处理FetchEvent
使用一个或多个
workbox-routing.Route
,如果满足以下条件,则返回 Response
:
存在匹配的路由。
如果没有与给定请求匹配的路由,路由器将使用“default” 处理程序。
如果匹配的路由抛出错误,路由器将使用“catch” 处理程序(如果定义了一个处理程序,以优雅地处理问题并使用 请求。
如果某个请求与多个路由匹配,则最早的注册路由将 用于响应请求。
属性
-
构造函数
void
初始化新的路由器。
constructor
函数如下所示:() => {...}
-
返回
-
-
路由
Map<HTTPMethodRoute[]>
-
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) => {...}
-
返回
对象
一个具有
route
和params
属性的对象。 如果找到了匹配的路由或undefined
,则会填充这些字段 否则。
-
-
handleRequest
void
将路由规则应用于 FetchEvent 对象,以从 相应 Route 的处理程序。
handleRequest
函数如下所示:(options: object) => {...}
-
选项
对象
-
事件
ExtendableEvent
触发 请求。
-
request
请求
要处理的请求。
-
-
返回
Promise<Response>
如果 就可以处理该请求如果没有匹配的 路线,并且没有
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(可选)
返回
-
生成的
Route
。
setCatchHandler()
workbox-routing.setCatchHandler(
handler: RouteHandler,
)
如果 Route 在处理请求时抛出错误,此 handler
将调用 ,并有机会给出响应。
参数
-
handler
回调 函数,该函数会返回 Promise 并产生 Response。
setDefaultHandler()
workbox-routing.setDefaultHandler(
handler: RouteHandler,
)
定义在没有显式路由时调用的默认 handler
与传入请求匹配。
如果没有默认处理程序,不匹配的请求将处理 就像没有 Service Worker 一样。
参数
-
handler
回调 函数,该函数会返回 Promise 并产生 Response。