-
Notifications
You must be signed in to change notification settings - Fork 319
ServiceWorkerAutoPreload #1756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ServiceWorkerAutoPreload #1756
Changes from all commits
33123c4
dd2b26b
3a53414
b1f4c5a
89fdc14
06eeb47
d436dce
c2070a7
74b9dc4
3daef71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3288,29 +3288,45 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ | |
1. Set |routedResponse|'s [=service worker timing info=]'s [=service worker timing info/worker final router source=] be set to |result|'s [=race result/used route=]. | ||
1. Return |routedResponse|. | ||
1. Assert: |source| is "{{RouterSourceEnum/fetch-event}}" | ||
1. If |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`<code>GET</code>\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] <code>fetch</code>, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set then: | ||
|
||
Note: If the above is true except |registration|'s [=active worker=]'s <a>set of event types to handle</a> **does not** contain <code>fetch</code>, then the user agent may wish to show a console warning, as the developer's intent isn't clear. | ||
|
||
1. Let |preloadRequest| be the result of [=request/cloning=] the request |request|. | ||
1. Let |preloadRequestHeaders| be |preloadRequest|'s [=request/header list=]. | ||
1. Let |preloadResponseObject| be a new {{Response}} object associated with a new {{Headers}} object whose [=guard=] is "`immutable`". | ||
1. [=header list/Append=] to |preloadRequestHeaders| a new [=header=] whose [=header/name=] is \`<code>Service-Worker-Navigation-Preload</code>\` and [=header/value=] is |registration|'s [=navigation preload header value=]. | ||
1. Set |preloadRequest|'s [=service-workers mode=] to "`none`". | ||
1. Let |preloadFetchController| be null. | ||
1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'s [=fetch controller/state=] is "<code>terminated</code>" or "<code>aborted</code>": | ||
1. Set |preloadFetchController| to the result of [=Fetch|fetching=] |preloadRequest|. | ||
|
||
To [=fetch/processResponse=] for |navigationPreloadResponse|, run these substeps: | ||
|
||
1. If |navigationPreloadResponse|'s [=response/type=] is "`error`", reject |preloadResponse| with a `TypeError` and terminate these substeps. | ||
1. Associate |preloadResponseObject| with |navigationPreloadResponse|. | ||
1. Resolve |preloadResponse| with |preloadResponseObject|. | ||
1. [=If aborted=], then: | ||
1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. | ||
1. [=fetch controller/Abort=] |preloadFetchController| with |deserializedError|. | ||
1. Let |responseForAutoPreload| be null. | ||
1. If |request| is a [=navigation request=], |request|'s [=request/method=] is \`<code>GET</code>\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] <code>fetch</code>, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set then: | ||
1. If |registration|'s [=navigation preload enabled flag=] is set then: | ||
|
||
Note: If the above is true except |registration|'s [=active worker=]'s <a>set of event types to handle</a> **does not** contain <code>fetch</code>, then the user agent may wish to show a console warning, as the developer's intent isn't clear. | ||
|
||
1. Let |preloadRequest| be the result of [=request/cloning=] the request |request|. | ||
1. Let |preloadRequestHeaders| be |preloadRequest|'s [=request/header list=]. | ||
1. Let |preloadResponseObject| be a new {{Response}} object associated with a new {{Headers}} object whose [=guard=] is "`immutable`". | ||
1. [=header list/Append=] to |preloadRequestHeaders| a new [=header=] whose [=header/name=] is \`<code>Service-Worker-Navigation-Preload</code>\` and [=header/value=] is |registration|'s [=navigation preload header value=]. | ||
1. Set |preloadRequest|'s [=service-workers mode=] to "`none`". | ||
1. Let |preloadFetchController| be null. | ||
1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'s [=fetch controller/state=] is "<code>terminated</code>" or "<code>aborted</code>": | ||
1. Set |preloadFetchController| to the result of [=Fetch|fetching=] |preloadRequest|. | ||
|
||
To [=fetch/processResponse=] for |navigationPreloadResponse|, run these substeps: | ||
|
||
1. If |navigationPreloadResponse|'s [=response/type=] is "`error`", reject |preloadResponse| with a `TypeError` and terminate these substeps. | ||
1. Associate |preloadResponseObject| with |navigationPreloadResponse|. | ||
1. Resolve |preloadResponse| with |preloadResponseObject|. | ||
1. [=If aborted=], then: | ||
1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. | ||
1. [=fetch controller/Abort=] |preloadFetchController| with |deserializedError|. | ||
1. Else if |timingInfo|'s [=service worker timing info/worker matched router source=] is not "{{RouterSourceEnum/fetch-event}}", a user agent may run the following substeps: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated not to introduce |source| here, use |timingInfo|'s [=service worker timing info/worker matched router source=] instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why doing autopreload if the route is NOT There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We frame the autopreload is an optional optimization that the browser can apply at its choosing. So we want to use the static routing API as an opt-out mechanism. If we only invoke the autopreload only when the matched router source is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see, I was mislead thinking that, at this point, the source could be other values like Maybe, it would be clearer if we would check if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! That sounds reasonable. Added |
||
|
||
Note: A user agent may speculatively dispatch a network request in parallel with creating a fetch event in order to minimize the bootstrap cost. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there sufficient description on when to do this speculative load? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the explainer, we mention two possible scenarios that the browser may invoke the autopreload. I don't think we can fully specify when it's used since some conditions are not deterministic, but do you think we should say more here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That might be ok as is. If there are cases where all browsers plan to do autopreload, we could be more precise, maybe with a SHOULD for instance. Say if the service worker is not running? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Let's keep it as is for now. Just to note: we're happy with rephrasing it with SHOULD. |
||
|
||
1. Assert: |timingInfo|'s [=service worker timing info/worker matched router source=] is null. | ||
1. Let |autoPreloadFetchController| be null. | ||
1. Set |responseForAutoPreload| to be a [=race response=] whose [=race response/value=] is "<code>pending</code>". | ||
1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'s [=fetch controller/state=] is "<code>terminated</code>" or "<code>aborted</code>": | ||
1. Set |autoPreloadFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |autoPreloadRequestResponse|: | ||
1. Set |responseForAutoPreload|'s [=race response/value=] to |autoPreloadRequestResponse|. | ||
1. [=If aborted=] and |autoPreloadFetchController| is not null, then: | ||
1. [=fetch controller/Abort=] |autoPreloadFetchController|. | ||
1. Set |responseForAutoPreload| to a [=race response=] whose [=race response/value=] is null. | ||
1. Resolve |preloadResponse| with undefined. | ||
1. Else, resolve |preloadResponse| with undefined. | ||
1. Let |fetchResult| be the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and null. | ||
1. Let |fetchResult| be the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |responseForAutoPreload|. | ||
sisidovski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
1. If |timingInfo|'s [=service worker timing info/worker final router source=] is not an empty string: | ||
1. Assert |timingInfo|'s [=service worker timing info/worker final router source=] is {{RouterSourceEnum/"network"}}. | ||
1. If |fetchResult| is null, then return |timingInfo|. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you explicitly skip subresource auto preload. just for note to myself.
https://github.com/WICG/service-worker-auto-preload?tab=readme-ov-file#auto-preload-for-subresources