Time To First Byte
Time to First Byte (TTFB) is a measurement used as an indication of the responsiveness of a webserver or other network resource. TTFB measures the duration from the user or client making an HTTP request to the first byte of the page being received by the client's browser.
Measure the time to first byte, from the server
Snippet
// Measure the time to first byte of all the resources loaded
// https://webperf-snippets.nucliweb.net
new PerformanceObserver((entryList) => {
const [pageNav] = entryList.getEntriesByType("navigation");
console.log(`TTFB (ms): ${pageNav.responseStart}`);
}).observe({
type: "navigation",
buffered: true,
});
Mesure the TTFB sub-parts
This snippet is part of pagespeed (opens in a new tab) by Arjen Karel (opens in a new tab)
Snippet
(() => {
const formatTime = (time) => {
//round by 2 decimals, use Math.round() for integer
return Math.round(time * 100) / 100;
};
new PerformanceObserver((entryList) => {
const [pageNav] = entryList.getEntriesByType('navigation');
// timing start times are relative
const activationStart = pageNav.activationStart || 0;
const workerStart = Math.max(pageNav.workerStart - activationStart, activationStart);
const dnsStart = Math.max(pageNav.domainLookupStart - activationStart, workerStart);
const tcpStart = Math.max(pageNav.connectStart - activationStart, dnsStart);
const sslStart = Math.max(pageNav.secureConnectionStart - activationStart, tcpStart);
const requestStart = Math.max(pageNav.requestStart - activationStart, sslStart);
const responseStart = Math.max(pageNav.responseStart - activationStart, requestStart);
// attribution based on https://www.w3.org/TR/navigation-timing-2/#processing-model
// use associative array to log the results more readable
let attributionArray = [];
attributionArray['Redirect Time'] = {'time in ms':formatTime(workerStart - activationStart)};
attributionArray['Worker and Cache Time'] = {'time in ms':formatTime(dnsStart - workerStart)};
attributionArray['DNS Time'] = {'time in ms':formatTime(tcpStart - dnsStart)};
attributionArray['TCP Time'] = {'time in ms':formatTime(sslStart - tcpStart)};
attributionArray['SSL Time'] = {'time in ms':formatTime(requestStart - sslStart)};
attributionArray['Request Time'] = {'time in ms':formatTime(responseStart - requestStart)};
attributionArray['Total TTFB'] = {'time in ms':formatTime(responseStart - activationStart)};
// log the results
console.log('%cTime to First Byte ('+formatTime(responseStart - activationStart)+'ms)', 'color: blue; font-weight: bold;');
console.table(attributionArray);
console.log('%cOrigininal navigation entry', 'color: blue; font-weight: bold;');
console.log(pageNav);
}).observe({
type: 'navigation',
buffered: true
});
})();
Measure the time to first byte of all the resources loaded
Snippet
// Measure the time to first byte of all the resources loaded
// https://webperf-snippets.nucliweb.net
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const resourcesLoaded = [...entries]
.map((entry) => {
let obj = {};
// Some resources may have a responseStart value of 0, due
// to the resource being cached, or a cross-origin resource
// being served without a Timing-Allow-Origin header set.
if (entry.responseStart > 0) {
obj = {
"TTFB (ms)": +entry.responseStart.toFixed(2),
Resource: entry.name,
};
}
return Object.keys(obj).length > 0 ? obj : undefined;
})
.filter((item) => item !== undefined);
console.table(resourcesLoaded);
}).observe({
type: "resource",
buffered: true,
});