-
Notifications
You must be signed in to change notification settings - Fork 22.8k
Document fetchLater()
#39016
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
Merged
Merged
Document fetchLater()
#39016
Changes from 54 commits
Commits
Show all changes
65 commits
Select commit
Hold shift + click to select a range
d619b1e
Fetch Later API
tunetheweb 1e7aa87
Merge branch 'main' into fetchLater
tunetheweb e6530a5
More updates
tunetheweb f0242d4
Rename api
tunetheweb ba424cd
Merge branch 'main' into fetchLater
tunetheweb 15beb78
Add quotas docs
tunetheweb f6948d6
Tweaks
tunetheweb a3eb7b6
Cleanup
tunetheweb 9f3d56d
Linting fix
tunetheweb 5d93bd4
Merge branch 'main' into fetchLater
tunetheweb 687e685
Linting fix
tunetheweb 92e22fb
Update PP docs
tunetheweb d83ed1e
Fix folder name
tunetheweb 94d7d7e
Fix example
tunetheweb 39286a9
Linting fixes
tunetheweb 65eab67
More linting fixes
tunetheweb a07075e
Merge branch 'main' into fetchLater
tunetheweb 77dcc29
Tweak
tunetheweb a372730
Explain example
tunetheweb 23ed99e
More linting
tunetheweb 5a12f6e
Add CSP and more exception details
tunetheweb e58c7b7
Update files/en-us/web/api/window/fetchlater/index.md
tunetheweb 6a7ae5e
Update files/en-us/web/api/window/fetchlater/index.md
tunetheweb 681b6eb
Update files/en-us/web/api/window/fetchlater/index.md
tunetheweb 2a335be
Update files/en-us/web/api/window/fetchlater/index.md
tunetheweb 0bf3d4f
more quota examples
tunetheweb fe78c27
Merge branch 'fetchLater' of github.com:tunetheweb/content into fetch…
tunetheweb 276eee0
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb 5b424b3
Review feedback
tunetheweb 11381ab
Merge branch 'main' into fetchLater
tunetheweb 8fa3838
Merge branch 'main' into fetchLater
chrisdavidmills 18af901
Accepting first batch of review feedback
tunetheweb 959601a
Second batch of suggestions from code review
tunetheweb 798c1c6
Update files/en-us/web/api/fetchlater_api/index.md
tunetheweb 5a50956
Update files/en-us/web/api/fetchlater_api/index.md
tunetheweb d5e475c
Update files/en-us/web/api/fetchlater_api/index.md
tunetheweb fe70212
Update files/en-us/web/api/fetchlater_api/index.md
tunetheweb 906da9f
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb c7d1f57
Update files/en-us/web/api/fetchlater_api/index.md
tunetheweb 7a84e61
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb e79e859
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb afe3e50
Update files/en-us/web/api/window/fetchlater/index.md
tunetheweb 0282158
Review feedback
tunetheweb 27bb9b8
Merge branch 'main' into fetchLater
tunetheweb 88a1418
Merge branch 'fetchLater' of github.com:tunetheweb/content into fetch…
tunetheweb 5bb4d29
Update files/en-us/web/api/fetchlaterresult/activated/index.md
tunetheweb 97cc500
Rename file
tunetheweb cf512b6
Merge branch 'fetchLater' of github.com:tunetheweb/content into fetch…
tunetheweb 5eab466
Meta cleanup
tunetheweb a65684b
Tweaks
tunetheweb b97ab4e
browser-compat for deferred-fetch and deferred-fetch-init
tunetheweb 9050e2a
Permissions Policy updates
tunetheweb 948a474
Apply suggestions from code review
tunetheweb 42ab726
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb 298b285
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb 826f7f4
Review feedback
tunetheweb f63717d
Merge branch 'main' into fetchLater
tunetheweb 44b6681
KB -> KiB
tunetheweb 0ff798c
Merge branch 'fetchLater' of github.com:tunetheweb/content into fetch…
tunetheweb 839e7fe
Permissions Policy BCD fixes
tunetheweb b614216
Frontmatter
tunetheweb 6171f01
Fetch Interfaces
tunetheweb 85607a4
Update files/en-us/web/api/deferredrequestinit/index.md
tunetheweb 566700d
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb 1d668e7
Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
tunetheweb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
files/en-us/web/api/deferredrequestinit/activateafter/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--- | ||
title: "DeferredRequestInit: activateAfter property" | ||
short-title: x | ||
slug: Web/API/DeferredRequestInit/activateAfter | ||
page-type: web-api-instance-property | ||
browser-compat: api.Window.fetchLater | ||
--- | ||
|
||
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}} | ||
|
||
The **`activateAfter`** property of the {{domxref("DeferredRequestInit")}} is a {{ domxref("DOMHighResTimeStamp") }} indicating a timeout in milliseconds after which the fetch request should be sent. | ||
|
||
The fetch can be sent earlier on navigating away. The _actual_ sending time is unknown, as the browser may wait for a longer or shorter time, for example, to optimize the batching of deferred fetches. If the `activateAfter` property is not provided, the deferred fetch waits until the end of the page visit (including entering the [bfcache](/en-US/docs/Glossary/bfcache)). | ||
|
||
## Value | ||
|
||
A {{ domxref("DOMHighResTimeStamp") }} timeout in milliseconds. | ||
|
||
## Examples | ||
|
||
### Defer a `POST` request for around one minute | ||
|
||
```js | ||
const result = fetchLater("https://report.example.com", { | ||
method: "POST", | ||
body: JSON.stringify(myReport), | ||
activateAfter: 60000 /* 1 minute */, | ||
}); | ||
``` | ||
|
||
## Specifications | ||
|
||
{{Specifications}} | ||
|
||
## Browser compatibility | ||
|
||
{{Compat}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
--- | ||
title: DeferredRequestInit | ||
slug: Web/API/DeferredRequestInit | ||
page-type: web-api-interface | ||
browser-compat: api.Window.fetchLater | ||
--- | ||
|
||
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}} | ||
|
||
The **`DeferredRequestInit`** dictionary of the [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API) represents the set of options that can be used to configure a deferred fetch request. | ||
|
||
The `DeferredRequestInit` object is passed directly into the {{domxref("window.fetchLater()")}} function call as the second argument. | ||
|
||
## Instance properties | ||
|
||
This dictionary extends the {{domxref("RequestInit")}} dictionary with the addition of the following properties: | ||
|
||
- {{domxref('DeferredRequestInit.activateAfter')}} {{optional_inline}} | ||
|
||
- : A {{ domxref("DOMHighResTimeStamp") }} indicating a timeout in milliseconds after which the fetch request should be sent. The fetch can be sent earlier on navigating away. The _actual_ sending time is unknown, as the browser may wait for a longer or shorter time, for example, to optimize the batching of deferred fetches. If the `activateAfter` property is not provided, the deferred fetch waits until the end of the page visit (including entering the [bfcache](/en-US/docs/Glossary/bfcache)). | ||
|
||
### Exceptions | ||
|
||
- `RangeError` {{domxref("DOMException")}} | ||
- : Raised when a negative `activateAfter` is provided. | ||
|
||
## Examples | ||
|
||
### Defer a `GET` request until the page is destroyed or enters the bfcache | ||
|
||
In this example, no `DeferredRequestInit` object is provided and no timeout is used: | ||
|
||
```js | ||
fetchLater("/send_beacon"); | ||
``` | ||
|
||
### Defer a `POST` request for around 1 minute | ||
|
||
In this example we create a {{domxref("Request")}}, and provide an `activateAfter` value to delay sending the request for 60,000 milliseconds (or one minute): | ||
|
||
```js | ||
fetchLater({ | ||
url: "/send_beacon" | ||
method: "POST" | ||
body: getBeaconData(), | ||
}, {activateAfter: 60000 /* 1 minute */}); | ||
``` | ||
|
||
> [!NOTE] | ||
> The actual sending time is unknown, as the browser may wait for a longer or shorter period of time, for example to optimize batching of deferred fetches. | ||
|
||
## Specifications | ||
|
||
{{Specifications}} | ||
|
||
## See also | ||
|
||
- [Using Fetch](/en-US/docs/Web/API/Fetch_API/Using_Fetch) | ||
- [ServiceWorker API](/en-US/docs/Web/API/Service_Worker_API) | ||
- [HTTP access control (CORS)](/en-US/docs/Web/HTTP/Guides/CORS) | ||
- [HTTP](/en-US/docs/Web/HTTP) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
182 changes: 182 additions & 0 deletions
182
files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
--- | ||
title: fetchLater() quotas | ||
slug: Web/API/fetchLater_API/fetchLater_quotas | ||
page-type: guide | ||
--- | ||
|
||
{{DefaultAPISidebar("fetchLater API")}} | ||
|
||
Deferred [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API) fetches are batched and sent once the tab is closed. At this point, there is no way for the user to abort them. To avoid situations where documents abuse this bandwidth to send unlimited amounts of data over the network the API sets quotas on how much data can be deferred to be sent later. | ||
|
||
These quotas can be managed through {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} and {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} [Permissions Policy](/en-US/docs/Web/HTTP/Guides/Permissions_Policy) directives. | ||
|
||
## Overview | ||
|
||
The overall quota for `fetchLater()` is 640KB per document. By default, this is divided into a 512KB top-level quota and a 128KB shared quota: | ||
|
||
- The 512KB top-level quota by default is for any `fetchLater()` requests made from the top-level document and direct subframes using that origin. | ||
- The 128KB shared quota by default is for any `fetchLater()` requests made in cross-origin subframes. | ||
|
||
`fetchLater()` requests can be made to any URL and are not restricted to the same origin as the document or the subframe, so it's important to differentiate between requests made in the top-level document content (whether to first-party or third-party origins) and those made in subframes. | ||
|
||
For example, if a top-level `a.com` document includes a `<script>` that makes a `fetchLater()` request to `analytics.example.com, this request would be bound by the top-level 512KB limit. Alternatively, if the top-level document embeds an`<iframe>`with a source of`analytics.example.com`that makes a`fetchLater()` request, that request would be bound by the 128KB limit. | ||
tunetheweb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Quota limits by reporting origin and subframe | ||
|
||
Only 64KB of the top-level 512KB quota can be used concurrently for the same reporting origin (the request URL's origin). This prevents third-party libraries from reserving quota opportunistically before they have data to send. | ||
|
||
Each cross-origin subframe gets an 8KB quota of the shared 128KB quota by default, allocated when the subframe is added to the DOM (whether `fetchLater()` will be used in that subframe or not). This means that, in general, only the first 16 cross-origin subframes added to a page can use `fetchLater()` as they will use up the 128KB quota. | ||
|
||
## Increasing subframe quotas by sharing the top-level quota | ||
|
||
The top-level origin can give selected cross-origin subframes an increased quota of 64KB, taking it out of the larger top-level 512KB limit. It does this by listing those origins in the {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} Permissions Policy directive. This is allocated when the subframe is added to the DOM, leaving less quota for the top-level document and direct same-origin subframes. Multiple same-origin subdomains can each get a 64KB quota. | ||
|
||
## Restricting the shared quota | ||
|
||
The top-level origin can also restrict the 128KB shared quota to named cross-origin subframes by listing those origins in the {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} Permissions Policy. It can also revoke the entire 128KB default subframe quota and instead keep the full 640KB quota for itself and any named `deferred-fetch` cross-origins by setting the {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} Permissions Policy to `()`. | ||
|
||
## Delegating quotes to subframes of subframes | ||
|
||
By default, subframes of subframes are not allocated a quota and so cannot use `fetchLater()`. Subframes allocated the increased 64KB quota can delegate the full 64KB quota to further subframes and allow them to use `fetchLater()` by setting their own `deferred-fetch` Permissions Policy. They can only delegate their full quota to further subframes, not parts of it, and cannot specify new quotas. Subframes using the minimal 8KB quota cannot delegate quotas to subframes. To be delegated quota, sub-subframes must be included in both the top-level and the subframe `deferred-fetch` {{httpheader('Permissions-Policy')}} directives. | ||
|
||
## When quotas are exceeded | ||
|
||
When quotas are exceeded, a `QuotaExceededError` is thrown when the {{domxref('Window.fetchLater()','fetchLater()')}} method is called to initiate the deferred request. | ||
|
||
Permissions Policy checks are not discernable from quota checks. Calling `fetchLater()` will throw a `QuotaExceededError` both if the quota is actually exceeded and if the quota was restricted for that origin via a Permissions Policy. | ||
|
||
Callers of `fetchLater()` should be defensive and catch `QuotaExceededError` errors in almost all cases, especially if they embed third-party JavaScript. | ||
|
||
## Examples | ||
|
||
### Using up the minimal quota | ||
|
||
```http | ||
Permissions-Policy: deferred-fetch=(self "https://b.com") | ||
``` | ||
|
||
1. A subframe of `b.com` receives 64KB upon creation, from the top-level's 512KB limit. | ||
tunetheweb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
2. A subframe of `c.com` is not listed and so receives 8KB upon creation from the 128KB shared limit. | ||
3. 15 more subframes would each receive 8KB upon creation (similar to `c.com`). | ||
4. The next subframe would not be granted any quota. | ||
5. If one of the subframes is removed, its deferred fetches will be sent. | ||
6. The next subframe _would_ receive an 8KB quota, as there is quota available again. | ||
|
||
### Revoking the minimal quota altogether with exceptions | ||
|
||
```http | ||
Permissions-Policy: deferred-fetch=(self "https://b.com") | ||
Permissions-Policy: deferred-fetch-minimal=() | ||
``` | ||
|
||
1. A subframe of `b.com` receives 64KB upon creation. | ||
2. A subframe of `c.com` receives no quota upon creation. | ||
3. The top-level document and its same-origin descendants can use up to the full 640KB but that is reduced to 574KB if a `b.com` subframe is created (or even less if multiple `b.com` subframes are created, each of which will be allocated a 64KB quota). | ||
|
||
### Revoking the minimal quota altogether with no exceptions | ||
|
||
```http | ||
Permissions-Policy: deferred-fetch-minimal=() | ||
``` | ||
|
||
1. The top-level document and its same-origin descendants can use up the full 640KB. | ||
2. Subframes are not allocated any quota and cannot use `fetchLater()`. | ||
|
||
### Same-origin subframes share quota with the top-level and can delegate to subframes | ||
|
||
Assuming a top-level document on `a.com`, which embeds a subframe of `a.com`, which embeds a subframe of `b.com`, and no explicit Permission Policies. | ||
|
||
1. The top-level document of `a.com` has the default 512KB quota. | ||
2. The subframe of `a.com` shares the 512KB quota. | ||
3. The subframe `b.com` receives an 8KB quota. | ||
tunetheweb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Same-origin subframes canot share quota with the top-level when separated by a cross-origin subframe | ||
|
||
Assuming a top-level document on `a.com`, which embeds a subframe of `b.com`, which embeds a subframe of `a.com`, and no explicit Permission Policies. | ||
|
||
1. The top-level frame of `a.com` has the default 512KB quota. | ||
2. The subframe of `b.com` shares the 8KB quota. | ||
3. The subframe `a.com` receives no quota; even though this is same-origin with the top origin, it is separated by a cross-origin. | ||
|
||
### Secondary subframes of subframes do not get quota by default | ||
|
||
Assuming a top-level document on `a.com`, which embeds a subframe of `b.com`, which embeds a subframe of `c.com`, and no explicit Permission Policies. | ||
|
||
1. The top-level frame of `a.com` has the default 512KB quota. | ||
2. The subframe of `b.com` receives 8KB of the default shared quota. | ||
3. The subframe `c.com` receives no quota. | ||
|
||
### Granting the full quota to a further subframe | ||
|
||
Assuming a top-level document on `a.com`, which embeds a subframe of `b.com`, which embeds a subframe of `c.com`. | ||
|
||
Assuming that `a.com` has the following Permissions Policy: | ||
|
||
```http | ||
Permissions-Policy: deferred-fetch=("https://c.com" "https://c.com") | ||
``` | ||
|
||
And, assuming that `b.com` has the following Permissions Policy: | ||
|
||
Permissions Policy of the following on `b.com`: | ||
tunetheweb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```http | ||
Permissions-Policy: deferred-fetch=("https://c.com") | ||
``` | ||
|
||
1. The top-level frame of `a.com` has the default 512KB quota. | ||
2. The subframe of `b.com` receives 64KB of the default shared quota. | ||
3. The subframe of `b.com` delegates its full quota of 8KB to `c.com`. `b.com` cannot use `fetchLater()`. | ||
4. The subframe `c.com` receives 8KB of quota. | ||
|
||
### Redirects do not transfer quota | ||
|
||
Assuming a top-level document on `a.com`, which embeds a subframe of `b.com`, which redirects to `c.com`, and no explicit top-level Permission Policies. | ||
|
||
1. The top-level frame of `a.com` has the default 512KB quota. | ||
2. The subframe of `b.com` receives 8KB of the default shared quota. | ||
3. The 8KB is not transferred to `c.com` when `b.com` redirects to there, but the 8KB is not released. | ||
|
||
### Redirects of subframes back to the top-level origin allow use of the top-level quota | ||
|
||
Assuming a top-level document on `a.com`, which embeds a subframe of `b.com`, which redirects to `a.com`, and no explicit top-level Permission Policies. | ||
|
||
1. The top-level frame of `a.com` has the default 512KB quota. | ||
2. The subframe of `b.com` receives 8KB of the default shared quota. | ||
3. The 8KB is not transferred to `a.com` when `b.com` redirects to there, but it is able to share the full top-level quota again, and the 8KB is released. | ||
|
||
### Examples which throw a `QuotaExceededError` | ||
|
||
```js | ||
// Maximum of 64KB per origin | ||
fetchLater(a_72_kb_url); | ||
|
||
// Maximum of 64KB per origin including headers | ||
fetchLater("https://origin.example.com", { headers: headers_exceeding_64kb }); | ||
|
||
// Maximum of 64KB per origin including body and headers | ||
fetchLater(a_32_kb_url, { headers: headers_exceeding_32kb }); | ||
|
||
// Maximum of 64KB per origin including body | ||
fetchLater("https://origin.example.com", { | ||
method: "POST", | ||
body: body_exceeding_64_kb, | ||
}); | ||
|
||
// Maximum of 64KB per origin including body and automatically added headers | ||
fetchLater(a_62_kb_url /* with a 3kb referrer */); | ||
``` | ||
|
||
### Examples which eventually throw a `QuotaExceededError` | ||
|
||
In the following sequence, contained in the top-level document, the first two requests would succeed, but the third would throw. That's because, even though the overall 640KB quota was not exceeded, the third request exceeds the reporting-origin quota for `https://a.example.com` and would throw. | ||
|
||
```js | ||
fetchLater("https://a.example.com", { method: "POST", body: a_40kb_body }); | ||
fetchLater("https://b.example.com", { method: "POST", body: a_40kb_body }); | ||
fetchLater("https://a.example.com", { method: "POST", body: a_40kb_body }); | ||
``` | ||
|
||
## See also | ||
|
||
- [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
--- | ||
title: fetchLater() API | ||
slug: Web/API/fetchLater_API | ||
page-type: web-api-overview | ||
browser-compat: api.Window.fetchLater | ||
--- | ||
|
||
{{DefaultAPISidebar("fetchLater API")}} | ||
|
||
The **`fetchLater()` API** provides an interface to request a deferred fetch that can be sent after a specified period of time, or when the page is closed or navigated away from. | ||
|
||
## Concepts and usage | ||
|
||
Developers often need to send (or beacon) data back to the server, particularly at the end of a user's visit to a page — for example, for analytics services. There are several ways to do this: from adding 1 pixel {{HTMLElement("img")}} elements to the page, to {{domxref("XMLHttpRequest")}}, to the dedicated {{domxref("Beacon API", "Beacon API", "", "nocode")}}, and the {{domxref("Fetch API", "Fetch API", "", "nocode")}} itself. | ||
|
||
The issue is that all of these methods suffer from reliability problems for end-of-visit beaconing. While the Beacon API and the {{domxref("Request.keepalive", "keepalive")}} property of the Fetch API will send data, even if the document is destroyed (to the best efforts that can be made in this scenario), this only solves part of the problem. | ||
|
||
The other — more difficult — part to solve concerns deciding _when_ to send the data, since there is not an ideal time in a page's lifecycle to make the JavaScript call to send out the beacon: | ||
|
||
- The {{domxref("Window.unload_event", "unload")}} and {{domxref("Window.beforeunload_event", "beforeunload")}} events are unreliable, and outright ignored by several major browsers. | ||
- The {{domxref("Window.pagehide_event", "pagehide")}} and {{domxref("document.visibilitychange_event", "visibilitychange")}} events are more reliable, but still have issues on mobile platforms. | ||
|
||
This means developers looking to reliably send out data via a beacon need to do so more frequently than is ideal. For example, they may send a beacon on each change, even if the final value for the page has not yet been reached. This has costs in network usage, server processing, and merging or discarding outdated beacons on the server. | ||
|
||
Alternatively, developers can choose to accept some level of missing data — either by: | ||
|
||
- Beaconing after a designated cut-off time and not collecting later data. | ||
- Beaconing at the end of the page lifecycle but accepting that sometimes this will not be reliable. | ||
|
||
The `fetchLater()` API extends the {{domxref("Fetch API")}} to allow setting fetch requests up in advance. These deferred fetches can be updated before they have been sent, allowing the payload to reflect the latest data to be beaconed. | ||
|
||
The browser then sends the beacon when the tab is closed or navigated away from, or after a set time if specified. This avoids sending multiple beacons but still ensures a reliable beacon within reasonable expectations (i.e., excluding when the browser process shuts down unexpectedly during a crash). | ||
|
||
Deferred fetches can also be aborted using an {{domxref("AbortController")}} if they are no longer required, avoiding further unnecessary costs. | ||
|
||
### Quotas | ||
|
||
Deferred fetches are batched and sent once the tab is closed; at this point, there is no way for the user to abort them. To avoid situations where documents abuse this bandwidth to send unlimited amounts of data over the network, the overall quota for a top-level document is capped at 640KB. | ||
|
||
Callers of `fetchLater()` should be defensive and catch `QuotaExceededError` errors in almost all cases, especially if they embed third-party JavaScript. | ||
|
||
Since this cap makes deferred fetch bandwidth a scarce resource, which needs to be shared between multiple reporting origins (for example, several RUM libraries) and subframes from multiple origins, the platform provides a reasonable default division of this quota. In addition, it provides {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} and {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} [Permissions Policy](/en-US/docs/Web/HTTP/Guides/Permissions_Policy) directives to allow dividing it differently when desired. | ||
|
||
See [fetchLater() quotas](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) for more details and examples. | ||
|
||
## Interfaces | ||
|
||
- {{domxref("Window.fetchLater()")}} | ||
- : Used to queue a resource for sending at a later point. | ||
- {{domxref("DeferredRequestInit")}} | ||
- : Represents the set of options that can be used to configure a deferred fetch request. | ||
- {{domxref("FetchLaterResult")}} | ||
- : Represents the result of requesting a deferred fetch. | ||
|
||
## HTTP headers | ||
|
||
- {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} | ||
tunetheweb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- : Controls [top-level quota](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) for the `fetchLater()` API. | ||
- {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} | ||
- : Controls [shared subframe quota](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) for the `fetchLater()` API. | ||
|
||
## Specifications | ||
|
||
{{Specifications}} | ||
|
||
## Browser compatibility | ||
|
||
{{Compat}} | ||
|
||
## See also | ||
|
||
- [`fetchLater()` quotas](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) | ||
- [Fetch API](/en-US/docs/Web/API/Fetch_API) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.