@foo-software/lighthouse-persist
Version:
A tool for persisting Lighthouse audit results used for website performance monitoring and analysis.
182 lines • 7.62 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const chromeLauncher_1 = require("./helpers/chromeLauncher");
const aws_sdk_1 = __importDefault(require("aws-sdk"));
const config_1 = __importDefault(require("./config"));
const options_1 = __importDefault(require("./options"));
const upload_1 = __importDefault(require("./helpers/upload"));
const getOpportunities_1 = __importDefault(require("./helpers/getOpportunities"));
const getPageSpeedInsightsApiResult_1 = __importDefault(require("./helpers/getPageSpeedInsightsApiResult"));
const loadLighthouse_1 = __importDefault(require("./helpers/loadLighthouse"));
const loadReportGenerator_1 = __importDefault(require("./helpers/loadReportGenerator"));
const PROTOCOL_TIMEOUT = 'PROTOCOL_TIMEOUT';
const createTimeout = (time) => new Promise((resolve) => {
setTimeout(resolve, time, PROTOCOL_TIMEOUT);
});
// https://github.com/GoogleChrome/lighthouse/blob/master/docs/readme.md#using-programmatically
exports.default = async ({ awsAccessKeyId: accessKeyId, awsBucket: Bucket, awsRegion: region, awsSecretAccessKey: secretAccessKey, config: customConfig, finalScreenshotAwsBucket, isExperimental, launchedChrome, options: customOptions, outputDirectory, updateReport, psiKey, timeout, url, verbose, }) => {
// will upload to S3?
const isS3 = !!(accessKeyId && region && secretAccessKey);
// if a URL, output directory, or S3 creds are missing - we got a problem.
if (!outputDirectory && !url && !isS3) {
throw new Error('Missing required params.');
}
// the default config combined with overriding query params
const fullConfig = {
...config_1.default,
...customConfig,
};
const options = {
...options_1.default,
...customOptions,
};
// we need to kill chrome if something goes wrong, so we pull it up
// into the function scope to be accessible in the catch block.
let chrome = launchedChrome;
try {
let results;
let loadingExperience;
let originLoadingExperience;
// this changed in Lighthouse 7, but we should try to support those
// who don't know about this obscure change.
const formFactor = fullConfig.settings.formFactor || fullConfig.settings.emulatedFormFactor;
// if we're getting results from the PageSpeed Insights API... else
// run Lighthouse directly
if (psiKey) {
const strategy = formFactor === 'desktop' ? 'DESKTOP' : 'MOBILE';
const psiResults = await (0, getPageSpeedInsightsApiResult_1.default)({
psiKey,
strategy,
url,
});
if (psiResults.error) {
throw Error(psiResults.error.message);
}
const ReportGenerator = await (0, loadReportGenerator_1.default)();
results = {
lhr: psiResults.lighthouseResult,
report: ReportGenerator.generateReportHtml(psiResults.lighthouseResult),
};
if (psiResults.loadingExperience) {
loadingExperience = psiResults.loadingExperience;
}
if (psiResults.originLoadingExperience) {
originLoadingExperience = psiResults.originLoadingExperience;
}
}
else {
if (!chrome) {
chrome = await (0, chromeLauncher_1.chromeLauncher)({
chromeFlags: options.chromeFlags,
port: options.port,
});
}
if (verbose) {
console.log('Chrome running on port', chrome.port);
}
options.output = 'html';
const lighthouse = await (0, loadLighthouse_1.default)();
results = !timeout
? await lighthouse(url, options, fullConfig)
: await Promise.race([
createTimeout(timeout),
lighthouse(url, options, fullConfig),
]);
if (results === PROTOCOL_TIMEOUT) {
throw Error(PROTOCOL_TIMEOUT);
}
await chrome.kill();
}
// a remote URL
let report;
// a local file path
let localReport;
// the final thumbnail image
let finalScreenshot;
const reportContent = !updateReport
? results.report
: updateReport(results.report);
if (isS3) {
if (Bucket && reportContent) {
// upload to S3
const s3Response = await (0, upload_1.default)({
s3bucket: new aws_sdk_1.default.S3({
accessKeyId,
region,
secretAccessKey,
}),
params: {
ACL: 'public-read',
Body: reportContent,
Bucket,
ContentType: 'text/html',
Key: `report-${Date.now()}.html`,
},
});
report = s3Response?.Location;
}
if (finalScreenshotAwsBucket) {
const finalScreenshotData = results?.lhr?.audits?.['final-screenshot']?.details?.data;
if (finalScreenshotData) {
const buffer = Buffer.from(finalScreenshotData.replace('data:image/jpeg;base64,', ''), 'base64');
const s3Response = await (0, upload_1.default)({
s3bucket: new aws_sdk_1.default.S3({
accessKeyId,
region,
secretAccessKey,
}),
params: {
ACL: 'public-read',
Body: buffer,
Bucket: finalScreenshotAwsBucket,
ContentEncoding: 'base64',
ContentType: 'image/jpeg',
Key: `final-screenshot-${Date.now()}.jpg`,
},
});
finalScreenshot = s3Response.Location;
}
}
}
if (outputDirectory) {
localReport = `${outputDirectory}/report-${Date.now()}.html`;
fs_1.default.writeFileSync(localReport, reportContent);
}
const parsedResult = JSON.parse(JSON.stringify(results.lhr));
let opportunities = [];
if (isExperimental && parsedResult?.categories?.performance?.auditRefs) {
try {
opportunities = await (0, getOpportunities_1.default)(parsedResult);
}
catch (error) {
console.error(error);
}
}
return {
finalScreenshot,
loadingExperience,
localReport,
originLoadingExperience,
result: parsedResult,
report,
// experimental features
...(!isExperimental
? {}
: {
opportunities,
}),
};
}
catch (error) {
// make sure we kill chrome
if (chrome) {
await chrome.kill();
}
throw error;
}
};
//# sourceMappingURL=lighthousePersist.js.map