Node.js: get the Time To First Byte (TTFB) of a website

Node.js: get the Time To First Byte (TTFB) of a website

In this tutorial we will see how to get the Time To First Byte (TTFB) of a website with Node.js.

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.