1、什么是Workbox Routing?
service worker可以攔截網(wǎng)頁的網(wǎng)絡(luò)請求,它可以把從網(wǎng)絡(luò)請求中緩存的或在Serv worker中請求獲取的內(nèi)容,返回給瀏覽器。也就是說瀏覽器不會再直接與服務(wù)器交互,轉(zhuǎn)而全權(quán)由service worker代理。
workbox-routing是一個模塊,可以很容易地將這些請求“路由”映射到不同的響應(yīng),并提供設(shè)置相應(yīng)策略的方法。
2、如何執(zhí)行routing
當(dāng)一個網(wǎng)絡(luò)請求觸發(fā)了service worker的fetch事件時,workbox-routing將嘗試使用提供的路由和處理程序響應(yīng)請求。

從上圖中,我們可以知道以下幾件重要的事情:
請求的類型很重要。默認(rèn)情況下,路由已注冊了“GET”請求的事件監(jiān)聽。 如果開發(fā)者希望攔截其他類型的請求,則需要指定額外的方法。
路由注冊的順序很重要。如果注冊了多個可以處理請求的路由,則首先注冊的路由將優(yōu)先響應(yīng)請求。
有幾種方法可以注冊路由,開發(fā)者可以使用回調(diào),正則表達(dá)式或路由實例,我們將在下面介紹每個實例。
3、路由的匹配和處理
workbox 的“路由傳入了兩個函數(shù):一個“匹配”函數(shù),用于確定路由是否應(yīng)該與請求匹配,一個“處理”函數(shù),它應(yīng)該處理請求并響應(yīng)。
Workbox提供了一些構(gòu)造器,它們將執(zhí)行匹配和處理,但如果想要不同的行為或響應(yīng),那么開發(fā)者可以編寫自定義匹配和處理函數(shù)。
匹配函數(shù)將被賦予FetchEvent和URL對象,開發(fā)者可以通過返回truthy值來匹配請求。 舉一個簡單的例子,匹配特定的URL,如下所示:
const matchCb = ({url, event}) => {
return (url.pathname === '/special/url');
};
通過來檢查/測試url或event.request匹配的請求,可以涵蓋大多數(shù)情況。
“處理程序”也將被賦予URL和事件,可以確定如何響應(yīng),無論是來自網(wǎng)絡(luò),還是來自緩存,還是生成在service worker中。
const handlerCb = ({url, event, params}) => {
return fetch(event.request)
.then((response) => {
return response.text();
})
.then((responseBody) => {
return new Response(`${responseBody} <!-- Look Ma. Added Content. -->`);
});
};
handler必須返回一個處理response的promise方法,使用如下方法可以注冊這些回調(diào)
workbox.routing.registerRoute(matchCb, handlerCb);
唯一的限制是“匹配”必須同步返回一個truthy值,你不能執(zhí)行任何異步工作。 這樣做的原因是Router 必須同步響應(yīng)獲取事件或允許下發(fā)到其他的獲取事件。
“handler”回調(diào)應(yīng)該返回一個解析為Response的Promise。 響應(yīng)的來源取決于開發(fā)者,網(wǎng)絡(luò)緩存或service worker生成的響應(yīng)。
通常,“處理程序”回調(diào)將使用workbox-strategy提供的策略之一,如下所示:
workbox.routing.registerRoute(
matchCb,
workbox.strategies.staleWhileRevalidate()
);
在此本文中,我們將重點關(guān)注workbox-routing,但你可以在workbox.strategies上了解有關(guān)這些策略的更多信息。
3、如何注冊正則表達(dá)式路由
通常的做法是使用正則表達(dá)式而不是“匹配”回調(diào)。 Workbox使這很容易實現(xiàn),如下所示:
workbox.routing.registerRoute(
new RegExp('/styles/.*\.css'),
handlerCb
);
對于同源的請求,只要請求的URL與正則表達(dá)式匹配,此正則表達(dá)式就會匹配。

上述三個路由都將被匹配
但是,對于跨域請求,正則表達(dá)式必須使用完整的URL開頭匹配。 這樣做的原因是,使用正則表達(dá)式new RegExp('/ styles /.* \ .css')不太可能與第三方CSS文件完全匹配。

如果你想匹配本地和第三方,可以在正則表達(dá)式的開頭使用通配符,但這應(yīng)該謹(jǐn)慎進(jìn)行,以確保它不會在Web應(yīng)用程序中導(dǎo)致意外行為。
4、如何注冊 Navigation Route
如果站點是單頁面應(yīng)用程序,則可以使用NavigationRoute返回所有導(dǎo)航請求的特定響應(yīng)。
workbox.routing.registerNavigationRoute('/single-page-app.html');
每當(dāng)用戶在瀏覽器中訪問你的網(wǎng)站時,該頁面的請求將成為導(dǎo)航請求,并將在緩存頁面“/single-page-app.html”中提供。 (注意:你應(yīng)該通過workbox-precaching或通過自己的安裝步驟緩存頁面)。
默認(rèn)情況下,這將響應(yīng)所有導(dǎo)航請求,如果您希望將其限制為響應(yīng)URL的子集,則可以使用白名單和黑名單選項來限制哪些頁面將匹配此路由。
workbox.routing.registerNavigationRoute('/single-page-app.html', {
whitelist: [
new RegExp('/blog/')
],
blacklist: [
new RegExp('/blog/restricted/'),
]
});
唯一需要注意的是,如果URL同時位于白名單和黑名單中,黑名單優(yōu)先。
5、設(shè)置默認(rèn)的處理函數(shù)
如果要為與路徑不匹配的請求提供“處理程序”,則可以設(shè)置默認(rèn)處理程序。
workbox.routing.setDefaultHandler(({url, event, params}) => {
...
});
6、設(shè)置catch handler
如果您的任何路由拋出錯誤,您可以通過設(shè)置catch處理程序來優(yōu)雅地捕獲和下發(fā)。
workbox.routing.setCatchHandler(({url, event, params}) => {
...
});
7、定義非GET請求的路由
默認(rèn)情況下,所有路由都假定為“GET”請求。
如果您想路由其他請求,例如“POST”請求,則需要在注冊請求時定義方法,如下所示:
workbox.routing.registerRoute(
matchCb,
handlerCb,
'POST'
);
workbox.routing.registerRoute(
new RegExp('/api/.*\.json'),
handlerCb,
'POST'
);
8、Router 日志
您應(yīng)該能夠使用來自workbox-routing的日志確定請求的流程,該日志將突出顯示通過Workbox處理的URL。

9、高級用法
如果您希望更好地控制何時向Workbox Router發(fā)出請求,您可以創(chuàng)建自己的路由器實例,并在需要使用路由器響應(yīng)請求時調(diào)用它的handleRequest()方法。
const router = new DefaultRouter();
self.addEventListener('fetch', (event) => {
const responsePromise = router.handleRequest(event);
if (responsePromise) {
// Router found a route to handle the request
event.respondWith(responsePromise);
} else {
// No route found to handle the request
}
});
直接使用路由器時,您還需要使用Route類或任何擴(kuò)展類來注冊路由。
const router = new DefaultRouter();
router.registerRoute(new Route(matchCb, handlerCb));
router.registerRoute(new RegExpRoute(new RegExp(...), handlerCb));
router.registerRoute(new NavigationRoute(handlerCb));
筆者個人訂閱號~歡迎小伙伴們關(guān)注
微信公眾號-感謝關(guān)注
若有疑問可以QQ聯(lián)系筆者,雖然不一定100%解決你的問題,但是可以交流探討一波:2276604211
順便打個廣告:如果有想入職中國銀聯(lián)上海技術(shù)開發(fā)的童鞋,也可以加上面的QQ資訊,筆者可以幫你回答一些相關(guān)問題~~
