Workbox Routing
参照元ページ: https://developers.google.com/web/tools/workbox/modules/workbox-routing
Workboxルーティングとは?
サービスワーカーはページに対するネットワークリクエストをインターセプト、つまり横取りできます。それによってブラウザへ返されるコンテンツは、キャッシュ経由、ネットワーク経由もしくはサービスワーカーが生成したものなど多岐に渡ります。
workbox-routing
を使うことで、リクエストに対する様々なレスポンスを返すためのルーティングの設定を簡単に行うことができます。
ルーティングがどのように行われるか
ネットワークへのリクエストがサービスワーカーのfetch
イベントを発火させる時、workbox-routing
は与えらたルートとハンドラーを使ってリクエストに対するレスポンスを返します。
上記の図で大切なことは:
- リクエストメソッドは重要です。デフォルトではルーティングは"GET"メソッドで指定されています。もし他のメソッドをインターセプトする場合は、明示的に渡してあげる必要があります。
- ルーティング登録の順番は大切です。一つにリクエストに対して複数のルーティングが設定されている場合は、一番最初に登録されているものがリクエストに対して有効になります。(補足: 上図で"Was there a matching Route?"で最初にマッチしたものが使用されるということですね)
ルーティングを登録するには、コールバック、正規表現、Route
インスタンスで行います。
ルートのマッチングとハンドリング
workboxのルーティングは二つの機能のみから成ります。
- マッチング: ルートがリクエストと一致しているかを決める
- ハンドリング: リクエストに対して
Response
でレスポンスを返す
Workboxはマッチングとハンドリングを行うヘルパー関数を持っていますが、もしそれとは異なる挙動を期待したい時はカスタムのマッチングとハンドリング関数を書くのがベストです。
マッチング関数はFetchEvent
とURL
オブジェクトを元にリクエストとマッチしているか否かの値を返します。簡単な例ですと、下記のように特定のURLとマッチさせることができます。
const matchCb = ({url, event}) => {
return (url.pathname === '/special/url');
}
ほとんどのユースケースはurl
かevent.request
がRequest
とマッチしているかを調べることでカバーされます。
ハンドラーでは与えられたurl
とevent
を元にどのようにレスポンスを返すかを決めることになります。それはネットワーク経由かキャッシュ経由、サービスワーカー(が生成したコンテンツ)経由かもしれません。
const handlerCb = ({url, event, params}) => {
return fetch(event.request)
.then((response) => {
return response.text()
})
.then((responseBody) => {
return new Response(`${responseBody} 例えばここにコンテンツを追加できます`)
})
}
ハンドラーはresolve
されたタイミングでResponse
を返すPromise
をリターンしなくはいけません。params
の値はmatch
関数の戻り値です。
これらのコールバックは次のように記述します。
workbox.routing.registerRoute(matchCb, handelrCb);
一つ注意しなくはいけないのは"match"関数は同期的に値を返すため、非同期では使えません。なぜなら、Router
はfetch
イベントやfetch
が失敗した場合のほかのfetch
イベントに同期的にレスポンスを返す必要があるからです。
通常"handler"関数はworkbox-strategies
で提供されているストラテジーを使います。
workbox.routing.regosterRoute(
matchCb,
new workbox.strategies.StaleWhileRevalidate()
);
ルーティングの正規表現の書き方
大抵のケースでは"match"の代わりに正規表現を使います。Workboxによってこの部分を簡単に書くことができます。
workbox.routing.registerRoute(
new RegExp('/styles/.*\.css'),
handlerCb
);
同一オリジンからのリクエストには、正規表現の適用が緩くなるため上記の書き方は次の3パターンでマッチします。
- https://example.com/styles/main.css
- https://example.com/styles/nested/file.css
- https://example.com/nested/styles/directory.css
しかし、クロスオリジンの場合はURLの先頭から一致する必要があります。想定外にサードパーティのアセットにマッチしてしまうことを防ぐためです。
- 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
そのためクロスオリジンのリクエストに対しては
new RegExp('https://cdn.third-party-site.com.*/styles/.*\.css')
のようにフルパスで記述します。