In this tutorial we will see how to get the Time To First Byte (TTFB) of a website with Node.js.
The TTFB is obtained by subtracting the SSL handshake timestamp from the timestamp in milliseconds of the start of data reception.
The data
event of the response
object can be used with the once()
event handler which is invoked when receiving the data for the very first time.
To get the SSL handshake timing instead, we need to access the secureConnect
event of the socket
object.
This object is available in the socket
event of the request
object.
'use strict';
const https = require('https');
const validator = require('validator');
const getTimeMS = hrTime => {
return (hrTime[0] * 1000) + (hrTime[1] / 1000000);
};
const getTimeDiff = results => {
const { responseBodyStart, tlsHandshake } = results;
return getTimeMS(responseBodyStart) - getTimeMS(tlsHandshake);
};
const getTTFB = host => {
if(!validator.isFQDN(host)) {
return Promise.reject(new Error('Invalid host.'));
}
const options = {
hostname: host,
port: 443,
method: 'GET'
};
return new Promise((resolve, reject) => {
const eventResults = {
dnsLookup: 0,
tcpConnection: 0,
tlsHandshake: 0,
responseBodyStart: 0,
responseBodyEnd: 0
};
const req = https.request(options, res => {
let body = '';
res.once('data', () => {
eventResults.responseBodyStart = process.hrtime();
});
res.on('data', d => {
body += d;
});
res.on('end', () => {
eventResults.responseBodyEnd = process.hrtime();
resolve({
ttfb: getTimeDiff(eventResults),
info: eventResults
});
});
});
req.on('error', error => {
reject(error);
});
req.on('socket', socket => {
socket.on('lookup', () => {
eventResults.dnsLookup = process.hrtime();
});
socket.on('connect', () => {
eventResults.tcpConnection = process.hrtime();
});
socket.on('secureConnect', () => {
eventResults.tlsHandshake = process.hrtime();
});
});
req.end();
});
};
process.hrtime()
returns an array with two integers, i.e. seconds and nanoseconds,
therefore to obtain a single timestamp in milliseconds, these values must be converted and added together.