psi-profiler-tool
Version:
Profile your url with lighthouse
150 lines (122 loc) • 5.64 kB
JavaScript
;
exports.psiApiFetch = psiApiFetch;
exports.default = profiler;
var _chalk = _interopRequireDefault(require("chalk"));
var _commonTags = require("common-tags");
var _isomorphicFetch = _interopRequireDefault(require("isomorphic-fetch"));
var _fp = require("lodash/fp");
var _flatten = _interopRequireDefault(require("ramda/src/flatten"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function makeId() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 6; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
const createArr = ({
runs,
view,
urls
}) => {
const viewRuns = view === 'both' ? ['desktop', 'mobile'] : view === 'mobile' ? ['mobile'] : ['desktop'];
return (0, _fp.pipe)((0, _fp.fill)(0, runs, urls), _flatten.default, (0, _fp.map)(url => viewRuns.map(run => `${url}&strategy=${run}`)), _flatten.default)(Array(runs));
};
async function psiApiFetch(url, waitAmount, verbose) {
const wait = ms => new Promise(res => setTimeout(res, ms));
return new Promise(async (res, rej) => {
try {
const resolve = await (0, _isomorphicFetch.default)(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${url}`);
const json = await resolve.json();
if (json && json.lighthouseResult && json.lighthouseResult.audits) {
const base = json.lighthouseResult;
const auditConstants = ['score', 'displayValue'];
const auditList = {
'categories.performance| Final Score:': null,
'audits.interactive| TTI:': null,
'audits.speed-index| Speed Index:': null,
'audits.first-contentful-paint| First Contentful Paint:': null,
'audits.first-cpu-idle| CPU Idle:': null,
'audits.first-meaningful-paint| Meaningful Paint:': null,
'audits.time-to-first-byte| Time To First Byte (TTFB):': null,
'audits.uses-long-cache-ttl| Uses Long Cache TTL:': null,
'audits.estimated-input-latency| Estimated Input Latency:': null,
'audits.bootup-time| JS Bootup Time:': null,
'audits.total-byte-weight| Total Byte Weight:': null,
'audits.mainthread-work-breakdown| Main Thread Work Time:': null
};
const result = Object.keys(auditList).reduce((auditResult, key) => _objectSpread({}, auditResult, {
[key.split('|')[1]]: (0, _fp.pipe)((0, _fp.getOr)('Data not found', key.split('|')[0]), (0, _fp.pick)(auditConstants))(base)
}), {});
if (verbose) {
console.table(result);
}
await wait(waitAmount);
res(result);
} else if (json.error && json.error.message) {
console.log(_chalk.default.bold.red('ERROR:'), json.error.message);
res('Error');
} else {
console.log(_chalk.default.bold.yellow('WARNING:'), 'Something went wrong, try using a different URL, or add more repeat runs.');
}
} catch (e) {
rej(e);
}
});
}
async function getResults(arr, waitAmount, api, verbose) {
return arr.reduce(async (previous, curr, index) => {
const collection = await previous;
const apiKey = api !== '' ? `&key=${api}` : '';
const fakeUrlChange = `${curr}${apiKey}&${makeId()}=${makeId()}`;
if (verbose) {
console.log(_chalk.default.bold.green(`Test #${index + 1}`), `${curr}`);
}
return _objectSpread({}, collection, {
[`${curr}-${index}`]: await psiApiFetch(fakeUrlChange, waitAmount, verbose)
});
}, {});
}
/**
*
* @typedef {Object} Options
* @property {number} runs - How many times to run PSI test on list of urls...
* @property {number} wait - How many ms to wait before running next test (useful if no api key)...
* @property {('mobile'|'desktop'|'both')} view - Which view to run tests for...
* @property {string} api - Google API key
* @property {boolean} verbose - Output console.log after every test...
*/
/**
* @param {...Options} options - `Object { runs, wait, view, api, verbose }`
* @param {array} urls - List of urls to provide the runner...
* @returns {Promise} promise
*/
async function profiler({
runs = 1,
wait = 2000,
view = 'both',
api = '',
verbose = false
}, ...urls) {
// normalize runs for later, array of all tests is
// how many runs * how many urls to test
runs = runs * urls.length;
if (verbose) {
console.log(_commonTags.stripIndents`
Runs: ${_chalk.default.bold.yellow(runs.toString())}
Waiting: ${_chalk.default.bold.yellow(wait.toString())}
Testing View: ${_chalk.default.bold.yellow(view)}
`);
}
const results = await getResults(createArr({
runs,
view,
urls
}), wait, api, verbose);
return results;
} // I want CommonJS primary import to be profiler
module.exports = profiler;
//# sourceMappingURL=index.js.map