NavigationRoute.ts
4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
import {assert} from 'workbox-core/_private/assert.js';
import {logger} from 'workbox-core/_private/logger.js';
import {RouteHandler, RouteMatchCallbackOptions} from 'workbox-core/types.js';
import {Route} from './Route.js';
import './_version.js';
export interface NavigationRouteMatchOptions {
allowlist?: RegExp[];
denylist?: RegExp[];
}
/**
* NavigationRoute makes it easy to create a
* {@link workbox-routing.Route} that matches for browser
* [navigation requests]{@link https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests}.
*
* It will only match incoming Requests whose
* {@link https://fetch.spec.whatwg.org/#concept-request-mode|mode}
* is set to `navigate`.
*
* You can optionally only apply this route to a subset of navigation requests
* by using one or both of the `denylist` and `allowlist` parameters.
*
* @memberof workbox-routing
* @extends workbox-routing.Route
*/
class NavigationRoute extends Route {
private readonly _allowlist: RegExp[];
private readonly _denylist: RegExp[];
/**
* If both `denylist` and `allowlist` are provided, the `denylist` will
* take precedence and the request will not match this route.
*
* The regular expressions in `allowlist` and `denylist`
* are matched against the concatenated
* [`pathname`]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname}
* and [`search`]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search}
* portions of the requested URL.
*
* *Note*: These RegExps may be evaluated against every destination URL during
* a navigation. Avoid using
* [complex RegExps](https://github.com/GoogleChrome/workbox/issues/3077),
* or else your users may see delays when navigating your site.
*
* @param {workbox-routing~handlerCallback} handler A callback
* function that returns a Promise resulting in a Response.
* @param {Object} options
* @param {Array<RegExp>} [options.denylist] If any of these patterns match,
* the route will not handle the request (even if a allowlist RegExp matches).
* @param {Array<RegExp>} [options.allowlist=[/./]] If any of these patterns
* match the URL's pathname and search parameter, the route will handle the
* request (assuming the denylist doesn't match).
*/
constructor(
handler: RouteHandler,
{allowlist = [/./], denylist = []}: NavigationRouteMatchOptions = {},
) {
if (process.env.NODE_ENV !== 'production') {
assert!.isArrayOfClass(allowlist, RegExp, {
moduleName: 'workbox-routing',
className: 'NavigationRoute',
funcName: 'constructor',
paramName: 'options.allowlist',
});
assert!.isArrayOfClass(denylist, RegExp, {
moduleName: 'workbox-routing',
className: 'NavigationRoute',
funcName: 'constructor',
paramName: 'options.denylist',
});
}
super(
(options: RouteMatchCallbackOptions) => this._match(options),
handler,
);
this._allowlist = allowlist;
this._denylist = denylist;
}
/**
* Routes match handler.
*
* @param {Object} options
* @param {URL} options.url
* @param {Request} options.request
* @return {boolean}
*
* @private
*/
private _match({url, request}: RouteMatchCallbackOptions): boolean {
if (request && request.mode !== 'navigate') {
return false;
}
const pathnameAndSearch = url.pathname + url.search;
for (const regExp of this._denylist) {
if (regExp.test(pathnameAndSearch)) {
if (process.env.NODE_ENV !== 'production') {
logger.log(
`The navigation route ${pathnameAndSearch} is not ` +
`being used, since the URL matches this denylist pattern: ` +
`${regExp.toString()}`,
);
}
return false;
}
}
if (this._allowlist.some((regExp) => regExp.test(pathnameAndSearch))) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(
`The navigation route ${pathnameAndSearch} ` + `is being used.`,
);
}
return true;
}
if (process.env.NODE_ENV !== 'production') {
logger.log(
`The navigation route ${pathnameAndSearch} is not ` +
`being used, since the URL being navigated to doesn't ` +
`match the allowlist.`,
);
}
return false;
}
}
export {NavigationRoute};