UNPKG

phantomas

Version:

Headless Chromium-based web performance metrics collector and monitoring tool

102 lines (88 loc) 3.41 kB
/** * Analyzes HTTP caching headers */ "use strict"; module.exports = function (phantomas) { var cacheControlRegExp = /max-age=(\d+)/; // @see https://developers.google.com/speed/docs/best-practices/caching function getCachingTime(url, headers) { // false means "no caching" var ttl = false, headerName, now = new Date(), headerDate; for (headerName in headers) { var value = headers[headerName]; switch (headerName.toLowerCase()) { // parse max-age=... // // max-age=2592000 // public, max-age=300, must-revalidate case "cache-control": var matches = value.match(cacheControlRegExp); if (matches) { ttl = parseInt(matches[1], 10); } break; case "expires": // catch Expires and Pragma headers case "pragma": case "x-pass-expires": // and Varnish specific headers case "x-pass-cache-control": phantomas.incrMetric("oldCachingHeaders"); // @desc number of responses with old, HTTP 1.0 caching headers (Expires and Pragma) phantomas.addOffender("oldCachingHeaders", { url, headerName, value, }); if (ttl === false) { headerDate = Date.parse(value); if (headerDate) ttl = Math.round((headerDate - now) / 1000); } break; } } //console.log(JSON.stringify(headers)); console.log("TTL: " + ttl + ' s'); return ttl; } phantomas.setMetric("cachingNotSpecified"); // @desc number of responses with no caching header sent (no Cache-Control header) phantomas.setMetric("cachingTooShort"); // @desc number of responses with too short (less than a week) caching time phantomas.setMetric("cachingDisabled"); // @desc number of responses with caching disabled (max-age=0) phantomas.setMetric("oldCachingHeaders"); phantomas.setMetric("cachingUseImmutable"); // @desc number of responses with a long TTL that can benefit from Cache-Control: immutable phantomas.on("recv", (entry) => { var ttl = getCachingTime(entry.url, entry.headers), headerName; // static assets if (entry.isImage || entry.isJS || entry.isCSS) { if (ttl === false) { phantomas.incrMetric("cachingNotSpecified"); phantomas.addOffender("cachingNotSpecified", entry.url); } else if (ttl <= 0) { phantomas.incrMetric("cachingDisabled"); phantomas.addOffender("cachingDisabled", entry.url); } else if (ttl < 7 * 86400) { phantomas.incrMetric("cachingTooShort"); phantomas.addOffender("cachingTooShort", { url: entry.url, ttl }); } else { // long TTL, suggest the use of Cache-Control: immutable (issue #683) for (headerName in entry.headers) { var value = entry.headers[headerName]; if (headerName.toLowerCase() === "cache-control") { if (/,\s?immutable/.test(value) === false) { phantomas.incrMetric("cachingUseImmutable"); phantomas.addOffender("cachingUseImmutable", { url: entry.url, ttl, }); } else { phantomas.log( "caching: Cache-Control: immutable used for <%s>", entry.url ); } } } } } }); };