From 91f3ded4354644fc88bbc52a4eb7abaac90906ce Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 21 Jan 2025 16:34:12 +0000 Subject: [PATCH 1/3] Add finalResponseHeadersStart docs --- .../finalresponseheadersstart/index.md | 103 ++++++++++++++++++ .../firstinterimresponsestart/index.md | 7 +- .../api/performanceresourcetiming/index.md | 6 +- .../requeststart/index.md | 4 + 4 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md diff --git a/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md b/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md new file mode 100644 index 000000000000000..48c01d7e19ee21a --- /dev/null +++ b/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md @@ -0,0 +1,103 @@ +--- +title: "PerformanceResourceTiming: finalResponseHeadersStart property" +short-title: finalResponseHeadersStart +slug: Web/API/PerformanceResourceTiming/finalResponseHeadersStart +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.PerformanceResourceTiming.finalResponseHeadersStart +--- + +{{APIRef("Performance API")}}{{AvailableInWorkers}}{{SeeCompatTable}} + +The **`finalResponseHeadersStart`** read-only property returns a {{domxref("DOMHighResTimeStamp","timestamp")}} immediately after the browser receives the first byte of the final document response (for example, 200 OK) from the server. + +This differs from **`{{domxref("PerformanceResourceTiming.requestStart", "requestStart")}}`** (which may also be represented as **`{{domxref("PerformanceResourceTiming.firstInterimResponseStart", "firstInterimResponseStart")}}`**) as this starts from the first bytes of any response including interim responses (for example, 103 Early Hints) with the final response coming potentially much later. + +When there are no interim responses, `requestStart` is the same as `finalResponseHeadersStart` and `firstInterimResponseStart` is 0. + +There is no _end_ property for `finalResponseHeadersStart`. + +## Value + +The `finalResponseHeadersStart` property can have the following values: + +- A {{domxref("DOMHighResTimeStamp")}} immediately after the browser receives the first bytes of the final response from the server. +- `0` if the resource is a cross-origin request and no {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header is used. + +## Examples + +### Measuring request time + +The `finalResponseHeadersStart` and {{domxref("PerformanceResourceTiming.requestStart", "requestStart")}} properties can be used to measure how long it takes to the browser to start receive the final response after the sending the request. + +```js +const request = entry.finalResponseHeadersStart - entry.requestStart; +``` + +The following example uses a {{domxref("PerformanceObserver")}} to notify of new `resource` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used for accessing entries from before the observer creation. + +```js +const observer = new PerformanceObserver((list) => { + list.getEntries().forEach((entry) => { + const request = entry.finalResponseHeadersStart - entry.requestStart; + if (request > 0) { + console.log(`${entry.name}: final response time: ${request}ms`); + } + }); +}); + +observer.observe({ type: "resource", buffered: true }); +``` + +The following example uses {{domxref("Performance.getEntriesByType()")}}, which only shows `resource` performance entries present in the browser's performance timeline at the time you call the method. + +```js +const resources = performance.getEntriesByType("resource"); +resources.forEach((entry) => { + const request = entry.finalResponseHeadersStart - entry.requestStart; + if (request > 0) { + console.log(`${entry.name}: final response time: ${request}ms`); + } +}); +``` + +The following example shnows how to measure the time between the first and final response headers. + +```js +const observer = new PerformanceObserver((list) => { + list.getEntries().forEach((entry) => { + const diff = entry.finalResponseHeadersStart - entry.responseStart; + if ((entry.finalResponseHeadersStart > 0) & (diff > 0)) { + console.log( + `${entry.name}: time between first and final response start: ${diff}ms`, + ); + } + }); +}); + +observer.observe({ type: "resource", buffered: true }); +``` + +### Cross-origin timing information + +If the value of the `finalResponseHeadersStart` property is `0`, the resource might be a cross-origin request. To allow seeing cross-origin timing information, the {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header needs to be set. + +For example, to allow `https://developer.mozilla.org` to see timing resources, the cross-origin resource should send: + +```http +Timing-Allow-Origin: https://developer.mozilla.org +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- {{HTTPHeader("Timing-Allow-Origin")}} +- {{domxref("PerformanceResourceTiming.firstInterimResponseStart", "firstInterimResponseStart")}} diff --git a/files/en-us/web/api/performanceresourcetiming/firstinterimresponsestart/index.md b/files/en-us/web/api/performanceresourcetiming/firstinterimresponsestart/index.md index d1b7fbad836b6ae..d097f6d92a02195 100644 --- a/files/en-us/web/api/performanceresourcetiming/firstinterimresponsestart/index.md +++ b/files/en-us/web/api/performanceresourcetiming/firstinterimresponsestart/index.md @@ -19,17 +19,19 @@ There is no _end_ property for `firstInterimResponseStart`. The `firstInterimResponseStart` property can have the following values: - A {{domxref("DOMHighResTimeStamp")}} immediately after the browser receives the first interim bytes of the response from the server. -- `0` if the resource sent no interim response +- `0` if the resource sent no interim response. - `0` if the resource is a cross-origin request and no {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header is used. > [!NOTE] > As Early Hints are typically only supported on the main navigation request, which is by definition same-origin, a `0` typically indicates Early Hints were **not** used. +When the `firstInterimResponseStart` is non-zero, that indicates it should be the same value as {{domxref("PerformanceResourceTiming.requestStart", "requestStart")}} for [supporting browsers](#browser_compatibility). + ## Examples ### Measuring request time -The `firstInterimResponseStart` and {{domxref("PerformanceResourceTiming.requestStart", "requestStart")}} properties can be used to measure how long it takes to the browser to receive an interim response after the sending the request. +The `firstInterimResponseStart` and `requestStart` properties can be used to measure how long it takes to the browser to receive an interim response after the sending the request. ```js const request = entry.firstInterimResponseStart - entry.requestStart; @@ -83,3 +85,4 @@ Timing-Allow-Origin: https://developer.mozilla.org ## See also - {{HTTPHeader("Timing-Allow-Origin")}} +- {{domxref("PerformanceResourceTiming.finalResponseHeadersStart", "finalResponseHeadersStart")}} diff --git a/files/en-us/web/api/performanceresourcetiming/index.md b/files/en-us/web/api/performanceresourcetiming/index.md index 21840e5fa9bd8af..dcd14d2ab1b90a2 100644 --- a/files/en-us/web/api/performanceresourcetiming/index.md +++ b/files/en-us/web/api/performanceresourcetiming/index.md @@ -22,7 +22,7 @@ The properties of this interface allow you to calculate certain resource timing - Measuring TCP handshake time (`connectEnd` - `connectStart`) - Measuring DNS lookup time (`domainLookupEnd` - `domainLookupStart`) - Measuring redirection time (`redirectEnd` - `redirectStart`) -- Measuring interim request time (`firstInterimResponseStart` - `requestStart`) +- Measuring interim request time (`firstInterimResponseStart` - `finalResponseHeadersStart`) - Measuring request time (`responseStart` - `requestStart`) - Measuring TLS negotiation time (`requestStart` - `secureConnectionStart`) - Measuring time to fetch (without redirects) (`responseEnd` - `fetchStart`) @@ -76,7 +76,9 @@ The interface supports the following timestamp properties which you can see in t - {{domxref('PerformanceResourceTiming.firstInterimResponseStart')}} {{experimental_inline}} {{ReadOnlyInline}} - : A {{domxref("DOMHighResTimeStamp")}} that represents the interim response time (for example, 100 Continue or 103 Early Hints). - {{domxref('PerformanceResourceTiming.responseStart')}} {{ReadOnlyInline}} - - : A {{domxref("DOMHighResTimeStamp")}} immediately after the browser receives the first byte of the response from the server. + - : A {{domxref("DOMHighResTimeStamp")}} immediately after the browser receives the first byte of the response from the server (which may be an interim response). +- {{domxref('PerformanceResourceTiming.finalResponseHeadersStart')}} {{experimental_inline}} {{ReadOnlyInline}} + - : A {{domxref("DOMHighResTimeStamp")}} that represents the final headers response time (for example, 200 Success), after any interim response time. - {{domxref('PerformanceResourceTiming.responseEnd')}} {{ReadOnlyInline}} - : A {{domxref("DOMHighResTimeStamp")}} immediately after the browser receives the last byte of the resource or immediately before the transport connection is closed, whichever comes first. diff --git a/files/en-us/web/api/performanceresourcetiming/requeststart/index.md b/files/en-us/web/api/performanceresourcetiming/requeststart/index.md index 9aed4c8621dac18..ca973324432f798 100644 --- a/files/en-us/web/api/performanceresourcetiming/requeststart/index.md +++ b/files/en-us/web/api/performanceresourcetiming/requeststart/index.md @@ -20,6 +20,10 @@ The `requestStart` property can have the following values: - `0` if the resource was instantaneously retrieved from a cache. - `0` if the resource is a cross-origin request and no {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header is used. +When the `firstInterimResponseStart` is non-zero, that indicates it should be the same value as {{domxref("PerformanceResourceTiming.requestStart", "requestStart")}} for [supporting browsers](#browser_compatibility). + +When there are no interim responses, `requestStart` is the same as `finalResponseHeadersStart` and `firstInterimResponseStart` is 0. + ## Examples ### Measuring request time From 2665a318e635a4e10083cde35a9e7e48a5d010c8 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 21 Jan 2025 17:15:37 +0000 Subject: [PATCH 2/3] Update TTFB definition --- files/en-us/glossary/time_to_first_byte/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/files/en-us/glossary/time_to_first_byte/index.md b/files/en-us/glossary/time_to_first_byte/index.md index af1e0a5afb123b5..1893afa5a427535 100644 --- a/files/en-us/glossary/time_to_first_byte/index.md +++ b/files/en-us/glossary/time_to_first_byte/index.md @@ -8,14 +8,17 @@ page-type: glossary-definition **Time to First Byte** (TTFB) refers to the time between the browser requesting a page and when it receives the first byte of information from the server. This time includes {{Glossary("DNS")}} lookup and establishing the connection using a {{Glossary("TCP")}} handshake and {{Glossary("TLS")}} handshake if the request is made over {{Glossary("HTTPS")}}. -TTFB is the time it takes between the start of the request and the start of the response, in milliseconds: +TTFB is the time it takes between the start of the request and the start of the response, in milliseconds. This can be measured using the `{{domxref("PerformanceResourceTiming.requestStart", "requestStart")}}` attribute of {{domxref("PerformanceNavigationTiming")}}: -```plain -TTFB = responseStart - navigationStart +```javascript +const ttfb = performance.getEntriesByType("navigation")[0].responseStart; ``` +> [!NOTE] +> For sites using {{HTTPStatus("103", "103 Early Hints")}} TTFB is typically the _first bytes_ (after any redirects) and so the 103 interim response. Site owners wishing to measure the time until the final response should use `{{domxref("PerformanceResourceTiming.finalResponseHeadersStart", "finalResponseHeadersStart")}}` where supported. + ## See also - [A typical HTTP session](/en-US/docs/Web/HTTP/Session) - [PerformanceResourceTiming](/en-US/docs/Web/API/PerformanceResourceTiming) -- [PerformanceTiming](/en-US/docs/Web/API/PerformanceTiming) +- [PerformanceNavigationTiming](/en-US/docs/Web/API/PerformanceNavigationTiming) From 9efee8b3c0cdbf8cdc3287eeccc959e0509be19e Mon Sep 17 00:00:00 2001 From: sideshowbarker Date: Wed, 22 Jan 2025 10:48:56 +0900 Subject: [PATCH 3/3] Apply suggestions from code review --- files/en-us/glossary/time_to_first_byte/index.md | 2 +- .../finalresponseheadersstart/index.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/files/en-us/glossary/time_to_first_byte/index.md b/files/en-us/glossary/time_to_first_byte/index.md index 1893afa5a427535..76f6eccbcc6fede 100644 --- a/files/en-us/glossary/time_to_first_byte/index.md +++ b/files/en-us/glossary/time_to_first_byte/index.md @@ -15,7 +15,7 @@ const ttfb = performance.getEntriesByType("navigation")[0].responseStart; ``` > [!NOTE] -> For sites using {{HTTPStatus("103", "103 Early Hints")}} TTFB is typically the _first bytes_ (after any redirects) and so the 103 interim response. Site owners wishing to measure the time until the final response should use `{{domxref("PerformanceResourceTiming.finalResponseHeadersStart", "finalResponseHeadersStart")}}` where supported. +> For sites using {{HTTPStatus("103", "103 Early Hints")}}, TTFB is typically the _first bytes_ (after any redirects) — and so, the 103 interim response. Site owners wishing to measure the time until the final response should use `{{domxref("PerformanceResourceTiming.finalResponseHeadersStart", "finalResponseHeadersStart")}}`, where supported. ## See also diff --git a/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md b/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md index 48c01d7e19ee21a..e2b50bc672699c1 100644 --- a/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md +++ b/files/en-us/web/api/performanceresourcetiming/finalresponseheadersstart/index.md @@ -12,7 +12,7 @@ browser-compat: api.PerformanceResourceTiming.finalResponseHeadersStart The **`finalResponseHeadersStart`** read-only property returns a {{domxref("DOMHighResTimeStamp","timestamp")}} immediately after the browser receives the first byte of the final document response (for example, 200 OK) from the server. -This differs from **`{{domxref("PerformanceResourceTiming.requestStart", "requestStart")}}`** (which may also be represented as **`{{domxref("PerformanceResourceTiming.firstInterimResponseStart", "firstInterimResponseStart")}}`**) as this starts from the first bytes of any response including interim responses (for example, 103 Early Hints) with the final response coming potentially much later. +This differs from **`{{domxref("PerformanceResourceTiming.requestStart", "requestStart")}}`** (which may also be represented as **`{{domxref("PerformanceResourceTiming.firstInterimResponseStart", "firstInterimResponseStart")}}`**), as this starts from the first bytes of any response including interim responses (for example, 103 Early Hints) with the final response coming potentially much later. When there are no interim responses, `requestStart` is the same as `finalResponseHeadersStart` and `firstInterimResponseStart` is 0. @@ -29,7 +29,7 @@ The `finalResponseHeadersStart` property can have the following values: ### Measuring request time -The `finalResponseHeadersStart` and {{domxref("PerformanceResourceTiming.requestStart", "requestStart")}} properties can be used to measure how long it takes to the browser to start receive the final response after the sending the request. +The `finalResponseHeadersStart` and {{domxref("PerformanceResourceTiming.requestStart", "requestStart")}} properties can be used to measure how long it takes for the browser to start receive the final response after the sending the request. ```js const request = entry.finalResponseHeadersStart - entry.requestStart; @@ -62,7 +62,7 @@ resources.forEach((entry) => { }); ``` -The following example shnows how to measure the time between the first and final response headers. +The following example shows how to measure the time between the first and final response headers. ```js const observer = new PerformanceObserver((list) => {