UNPKG

@foo-software/lighthouse-persist

Version:

A tool for persisting Lighthouse audit results used for website performance monitoring and analysis.

182 lines 7.62 kB
"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