Skip to content

Commit a206852

Browse files
klemenoslajmhevery
authored andcommitted
feat(service-worker): add the option to prefer network for navigation requests (#38565)
This commit introduces a new option for the service worker, called `navigationRequestStrategy`, which adds the possibility to force the service worker to always create a network request for navigation requests. This enables the server redirects while retaining the offline behavior. Fixes #38194 PR Close #38565
1 parent 145ab3d commit a206852

File tree

13 files changed

+120
-0
lines changed

13 files changed

+120
-0
lines changed

aio/content/guide/service-worker-config.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,12 @@ By default, these criteria are:
267267
1. The URL must not contain a file extension (i.e. a `.`) in the last path segment.
268268
2. The URL must not contain `__`.
269269

270+
<div class="alert is-helpful">
271+
272+
To configure whether navigation requests are sent through to the network or not, see the [navigationRequestStrategy](#navigation-request-strategy) section.
273+
274+
</div>
275+
270276
### Matching navigation request URLs
271277

272278
While these default criteria are fine in most cases, it is sometimes desirable to configure different rules. For example, you may want to ignore specific routes (that are not part of the Angular app) and pass them through to the server.
@@ -285,3 +291,32 @@ If the field is omitted, it defaults to:
285291
'!/**/*__*/**', // Exclude URLs containing `__` in any other segment.
286292
]
287293
```
294+
295+
{@a navigation-request-strategy}
296+
297+
## `navigationRequestStrategy`
298+
299+
This optional property enables you to configure how the service worker handles navigation requests:
300+
301+
```json
302+
{
303+
"navigationRequestStrategy": "freshness"
304+
}
305+
```
306+
307+
Possible values:
308+
309+
- `'performance'`: The default setting. Serves the specified [index file](#index-file), which is typically cached.
310+
- `'freshness'`: Passes the requests through to the network and falls back to the `performance` behavior when offline.
311+
This value is useful when the server redirects the navigation requests elsewhere using an HTTP redirect (3xx status code).
312+
Reasons for using this value include:
313+
- Redirecting to an authentication website when authentication is not handled by the application.
314+
- Redirecting specific URLs to avoid breaking existing links/bookmarks after a website redesign.
315+
- Redirecting to a different website, such as a server-status page, while a page is temporarily down.
316+
317+
<div class="alert is-important">
318+
319+
The `freshness` strategy usually results in more requests sent to the server, which can increase response latency.
320+
It is recommended that you use the default performance strategy whenever possible.
321+
322+
</div>

goldens/public-api/service-worker/config/config.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export declare interface Config {
1414
assetGroups?: AssetGroup[];
1515
dataGroups?: DataGroup[];
1616
index: string;
17+
navigationRequestStrategy?: 'freshness' | 'performance';
1718
navigationUrls?: string[];
1819
}
1920

packages/service-worker/config/schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@
161161
"type": "string"
162162
},
163163
"uniqueItems": true
164+
},
165+
"navigationRequestStrategy": {
166+
"enum": [
167+
"freshness",
168+
"performance"
169+
],
170+
"default": "performance",
171+
"description": "The Angular service worker can use two request strategies for navigation requests. 'performance', the default, skips navigation requests. The other strategy, 'freshness', forces all navigation requests through the network."
164172
}
165173
},
166174
"required": [

packages/service-worker/config/src/generator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export class Generator {
3939
dataGroups: this.processDataGroups(config),
4040
hashTable: withOrderedKeys(unorderedHashTable),
4141
navigationUrls: processNavigationUrls(this.baseHref, config.navigationUrls),
42+
navigationRequestStrategy: config.navigationRequestStrategy ?? 'performance',
4243
};
4344
}
4445

packages/service-worker/config/src/in.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface Config {
2727
assetGroups?: AssetGroup[];
2828
dataGroups?: DataGroup[];
2929
navigationUrls?: string[];
30+
navigationRequestStrategy?: 'freshness'|'performance';
3031
}
3132

3233
/**

packages/service-worker/config/test/generator_spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ describe('Generator', () => {
117117
{positive: true, regex: '^http:\\/\\/example\\.com\\/included$'},
118118
{positive: false, regex: '^http:\\/\\/example\\.com\\/excluded$'},
119119
],
120+
navigationRequestStrategy: 'performance',
120121
hashTable: {
121122
'/test/foo/test.html': '18f6f8eb7b1c23d2bb61bff028b83d867a9e4643',
122123
'/test/index.html': 'a54d88e06612d820bc3be72877c74f257b561b19',
@@ -149,6 +150,7 @@ describe('Generator', () => {
149150
{positive: false, regex: '^\\/(?:.+\\/)?[^/]*__[^/]*$'},
150151
{positive: false, regex: '^\\/(?:.+\\/)?[^/]*__[^/]*\\/.*$'},
151152
],
153+
navigationRequestStrategy: 'performance',
152154
hashTable: {},
153155
});
154156
});
@@ -249,6 +251,7 @@ describe('Generator', () => {
249251
{positive: false, regex: '^\\/(?:.+\\/)?[^/]*__[^/]*$'},
250252
{positive: false, regex: '^\\/(?:.+\\/)?[^/]*__[^/]*\\/.*$'},
251253
],
254+
navigationRequestStrategy: 'performance',
252255
hashTable: {
253256
'/index.html': 'a54d88e06612d820bc3be72877c74f257b561b19',
254257
'/main.js': '41347a66676cdc0516934c76d9d13010df420f2c',

packages/service-worker/test/integration_spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const manifest: Manifest = {
4747
cacheQueryOptions: {ignoreVary: true},
4848
}],
4949
navigationUrls: [],
50+
navigationRequestStrategy: 'performance',
5051
hashTable: tmpHashTableForFs(dist),
5152
};
5253

@@ -64,6 +65,7 @@ const manifestUpdate: Manifest = {
6465
cacheQueryOptions: {ignoreVary: true},
6566
}],
6667
navigationUrls: [],
68+
navigationRequestStrategy: 'performance',
6769
hashTable: tmpHashTableForFs(distUpdate),
6870
};
6971

packages/service-worker/worker/src/app-version.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ export class AppVersion implements UpdateSource {
185185
// Next, check if this is a navigation request for a route. Detect circular
186186
// navigations by checking if the request URL is the same as the index URL.
187187
if (this.adapter.normalizeUrl(req.url) !== this.indexUrl && this.isNavigationRequest(req)) {
188+
if (this.manifest.navigationRequestStrategy === 'freshness') {
189+
// For navigation requests the freshness was configured. The request will always go trough
190+
// the network and fallback to default `handleFetch` behavior in case of failure.
191+
try {
192+
return await this.scope.fetch(req);
193+
} catch {
194+
// Navigation request failed - application is likely offline.
195+
// Proceed forward to the default `handleFetch` behavior, where
196+
// `indexUrl` will be requested and it should be available in the cache.
197+
}
198+
}
199+
188200
// This was a navigation request. Re-enter `handleFetch` with a request for
189201
// the URL.
190202
return this.handleFetch(this.adapter.newRequest(this.indexUrl), context);

packages/service-worker/worker/src/manifest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface Manifest {
1818
assetGroups?: AssetGroupConfig[];
1919
dataGroups?: DataGroupConfig[];
2020
navigationUrls: {positive: boolean, regex: string}[];
21+
navigationRequestStrategy: 'freshness'|'performance';
2122
hashTable: {[url: string]: string};
2223
}
2324

packages/service-worker/worker/test/data_spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ const manifest: Manifest = {
9393
},
9494
],
9595
navigationUrls: [],
96+
navigationRequestStrategy: 'performance',
9697
hashTable: tmpHashTableForFs(dist),
9798
};
9899

0 commit comments

Comments
 (0)