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 waitEnd = Math.max((pageNav.workerStart || pageNav.fetchStart) - activationStart, 0);
const dnsStart = Math.max(pageNav.domainLookupStart - activationStart, 0);
const tcpStart = Math.max(pageNav.connectStart - activationStart, 0);
const sslStart = Math.max(pageNav.secureConnectionStart - activationStart, 0);
const tcpEnd = Math.max(pageNav.connectEnd - activationStart, 0);
const responseStart = Math.max(pageNav.responseStart - activationStart, 0);
// 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 and Waiting duration'] = {'time in ms':formatTime(waitEnd)};
attributionArray['Worker and Cache duration'] = {'time in ms':formatTime(dnsStart - waitEnd)};
attributionArray['DNS duration'] = {'time in ms':formatTime(tcpStart - dnsStart)};
attributionArray['TCP duration'] = {'time in ms':formatTime(sslStart - tcpStart)};
attributionArray['SSL duration'] = {'time in ms':formatTime(tcpEnd - sslStart)};
attributionArray['Request duration'] = {'time in ms':formatTime(responseStart - tcpEnd)};
attributionArray['Total TTFB'] = {'time in ms':formatTime(responseStart)};
// 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,
});