Skip to content

Commit 8c1bc8d

Browse files
Integrate fetchLater() API into Fetch (mdn#42693)
* Move fetchlater API docs into fetch API * Fix a typo * Merge fetchLater groupdata into fetch * Fix sidebars * Delete and redirect fetchlater API pages; update links * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Add more links * Reword fetchLater description --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 64f819b commit 8c1bc8d

File tree

11 files changed

+102
-140
lines changed

11 files changed

+102
-140
lines changed

files/en-us/_redirects.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11224,6 +11224,8 @@
1122411224
/en-US/docs/Web/API/event.view /en-US/docs/Web/API/UIEvent/view
1122511225
/en-US/docs/Web/API/event.which /en-US/docs/Web/API/UIEvent/which
1122611226
/en-US/docs/Web/API/fetch /en-US/docs/Web/API/Window/fetch
11227+
/en-US/docs/Web/API/fetchLater_API /en-US/docs/Web/API/Fetch_API
11228+
/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas /en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch
1122711229
/en-US/docs/Web/API/form.acceptCharset /en-US/docs/Web/API/HTMLFormElement/acceptCharset
1122811230
/en-US/docs/Web/API/form.action /en-US/docs/Web/API/HTMLFormElement/action
1122911231
/en-US/docs/Web/API/form.elements /en-US/docs/Web/API/HTMLFormElement/elements

files/en-us/web/api/deferredrequestinit/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ status:
77
browser-compat: api.Window.fetchLater
88
---
99

10-
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}}
10+
{{DefaultAPISidebar("Fetch API")}}{{SeeCompatTable}}
1111

12-
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.
12+
The **`DeferredRequestInit`** dictionary of the [Fetch API](/en-US/docs/Web/API/Fetch_API) represents the set of options that can be used to configure a deferred fetch request.
1313

1414
The `DeferredRequestInit` object is passed directly into the {{domxref("window.fetchLater()")}} function call as the second argument.
1515

@@ -60,7 +60,7 @@ fetchLater("/send_beacon", {
6060

6161
## See also
6262

63-
- [Using Fetch](/en-US/docs/Web/API/Fetch_API/Using_Fetch)
63+
- [Using Deferred Fetch](/en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch)
6464
- [ServiceWorker API](/en-US/docs/Web/API/Service_Worker_API)
6565
- [HTTP access control (CORS)](/en-US/docs/Web/HTTP/Guides/CORS)
6666
- [HTTP](/en-US/docs/Web/HTTP)

files/en-us/web/api/fetch_api/index.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
title: Fetch API
33
slug: Web/API/Fetch_API
44
page-type: web-api-overview
5-
browser-compat: api.fetch
5+
browser-compat:
6+
- api.fetch
7+
- api.Window.fetchLater
68
---
79

8-
{{DefaultAPISidebar("Fetch API")}} {{AvailableInWorkers}}
10+
{{DefaultAPISidebar("Fetch API")}}
911

1012
The Fetch API provides an interface for fetching resources (including across the network). It is a more powerful and flexible replacement for {{DOMxRef("XMLHttpRequest")}}.
1113

@@ -23,17 +25,34 @@ You can create a request and response directly using the {{DOMxRef("Request.Requ
2325

2426
Find out more about using the Fetch API features in [Using Fetch](/en-US/docs/Web/API/Fetch_API/Using_Fetch).
2527

28+
### Deferred Fetch
29+
30+
The {{domxref("Window/fetchLater", "fetchLater()")}} API enables a developer 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. See [Using Deferred Fetch](/en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch).
31+
2632
## Interfaces
2733

2834
- {{domxref("Window.fetch()")}} and {{domxref("WorkerGlobalScope.fetch()")}}
2935
- : The `fetch()` method used to fetch a resource.
36+
- {{domxref("Window.fetchLater()")}}
37+
- : Used to make a deferred fetch request.
38+
- {{domxref("DeferredRequestInit")}}
39+
- : Represents the set of options that can be used to configure a deferred fetch request.
40+
- {{domxref("FetchLaterResult")}}
41+
- : Represents the result of requesting a deferred fetch.
3042
- {{DOMxRef("Headers")}}
3143
- : Represents response/request headers, allowing you to query them and take different actions depending on the results.
3244
- {{DOMxRef("Request")}}
3345
- : Represents a resource request.
3446
- {{DOMxRef("Response")}}
3547
- : Represents the response to a request.
3648

49+
## HTTP headers
50+
51+
- {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}}
52+
- : Controls the [top-level quota](/en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch#quotas) for the `fetchLater()` API.
53+
- {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}}
54+
- : Controls the [shared cross-origin subframe quota](/en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch#quotas) for the `fetchLater()` API.
55+
3756
## Specifications
3857

3958
{{Specifications}}

files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md renamed to files/en-us/web/api/fetch_api/using_deferred_fetch/index.md

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,45 @@
11
---
2-
title: fetchLater() quotas
3-
slug: Web/API/fetchLater_API/fetchLater_quotas
2+
title: Using Deferred Fetch
3+
slug: Web/API/Fetch_API/Using_Deferred_Fetch
44
page-type: guide
5-
status:
6-
- experimental
7-
browser-compat:
8-
- http.headers.Permissions-Policy.deferred-fetch
9-
- http.headers.Permissions-Policy.deferred-fetch-minimal
105
---
116

12-
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}}
7+
{{DefaultAPISidebar("Fetch API")}}
138

14-
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.
15-
16-
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.
9+
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.
1710

1811
## Overview
1912

13+
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.
14+
15+
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.
16+
17+
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:
18+
19+
- The {{domxref("Window.unload_event", "unload")}} and {{domxref("Window.beforeunload_event", "beforeunload")}} events are unreliable, and outright ignored by several major browsers.
20+
- The {{domxref("Window.pagehide_event", "pagehide")}} and {{domxref("document.visibilitychange_event", "visibilitychange")}} events are more reliable, but still have issues on mobile platforms.
21+
22+
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.
23+
24+
Alternatively, developers can choose to accept some level of missing data — either by:
25+
26+
- Beaconing after a designated cut-off time and not collecting later data.
27+
- Beaconing at the end of the page lifecycle but accepting that sometimes this will not be reliable.
28+
29+
The `fetchLater()` API extends the {{domxref("Fetch API", "Fetch API", "", "nocode")}} 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.
30+
31+
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).
32+
33+
Deferred fetches can also be aborted using an {{domxref("AbortController")}} if they are no longer required, avoiding further unnecessary costs.
34+
35+
## Quotas
36+
37+
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 640KiB.
38+
39+
Callers of `fetchLater()` should be defensive and catch `QuotaExceededError` errors in almost all cases, especially if they embed third-party JavaScript.
40+
41+
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.
42+
2043
The overall quota for `fetchLater()` is 640KiB per document. By default, this is divided into a 512KiB top-level quota and a 128KiB shared quota:
2144

2245
- The 512KiB top-level quota by default is for any `fetchLater()` requests made from the top-level document and direct subframes using that origin.
@@ -26,33 +49,33 @@ The overall quota for `fetchLater()` is 640KiB per document. By default, this is
2649

2750
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 512KiB 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 128KiB limit.
2851

29-
## Quota limits by reporting origin and subframe
52+
### Quota limits by reporting origin and subframe
3053

3154
Only 64KiB of the top-level 512KiB 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.
3255

3356
Each cross-origin subframe gets an 8KiB quota out of the shared 128KiB 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 128KiB quota.
3457

35-
## Increasing subframe quotas by sharing the top-level quota
58+
### Increasing subframe quotas by sharing the top-level quota
3659

3760
The top-level origin can give selected cross-origin subframes an increased quota of 64KiB, taking it out of the larger top-level 512KiB 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 64KiB quota.
3861

39-
## Restricting the shared quota
62+
### Restricting the shared quota
4063

4164
The top-level origin can also restrict the 128KiB 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 128KiB default subframe quota and instead keep the full 640KiB 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 `()`.
4265

43-
## Delegating quotes to subframes of subframes
66+
### Delegating quotes to subframes of subframes
4467

4568
By default, subframes of subframes are not allocated a quota and so cannot use `fetchLater()`. Subframes allocated the increased 64KiB quota can delegate the full 64KiB 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 8KiB 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.
4669

47-
## When quotas are exceeded
70+
### When quotas are exceeded
4871

4972
When quotas are exceeded, a `QuotaExceededError` is thrown when the {{domxref('Window.fetchLater()','fetchLater()')}} method is called to initiate the deferred request.
5073

5174
Permissions Policy checks are not discernible 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.
5275

5376
Callers of `fetchLater()` should be defensive and catch `QuotaExceededError` errors in almost all cases, especially if they embed third-party JavaScript.
5477

55-
## Examples
78+
## Quota examples
5679

5780
### Using up the minimal quota
5881

@@ -212,15 +235,3 @@ Assuming a top-level document at `a.com`, which embeds `<iframe src="https://b.c
212235
1. The top-level frame of `a.com` has the default 512KiB quota.
213236
2. `<iframe src="https://b.com/">` receives 8KiB of the default shared quota of 128KiB.
214237
3. The 8KiB is not transferred to `a.com` when `<iframe src="https://b.com/">` redirects there, but it can share the full top-level quota again, and the previously-allocated 8KiB quota is released.
215-
216-
## Specifications
217-
218-
{{Specifications}}
219-
220-
## Browser compatibility
221-
222-
{{Compat}}
223-
224-
## See also
225-
226-
- [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API)

files/en-us/web/api/fetchlater_api/index.md

Lines changed: 0 additions & 75 deletions
This file was deleted.

files/en-us/web/api/fetchlaterresult/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ status:
77
browser-compat: api.FetchLaterResult
88
---
99

10-
{{APIRef("fetchLater API")}}{{SeeCompatTable}}
10+
{{APIRef("Fetch API")}}{{SeeCompatTable}}
1111

12-
The **`FetchLaterResult`** interface of the [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API) is returned by the {{domxref("Window.fetchLater()")}} method after a deferred fetch has been created.
12+
The **`FetchLaterResult`** interface of the [Fetch API](/en-US/docs/Web/API/Fetch_API) is returned by the {{domxref("Window.fetchLater()")}} method after a deferred fetch has been created.
1313

1414
It contains a single `activated` property that indicates whether the deferred request has been sent out or not.
1515

@@ -46,5 +46,5 @@ function checkIfFetched() {
4646

4747
## See also
4848

49-
- [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API)
5049
- [Fetch API](/en-US/docs/Web/API/Fetch_API)
50+
- [Using Deferred Fetch](/en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch)

0 commit comments

Comments
 (0)