Automated auditing, performance metrics, and best practices for the web.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Lighthouse report generation transforms audit results into various output formats for analysis, sharing, and integration with other tools. The reporting system supports multiple formats and provides both programmatic and file-based output options.
Generates formatted reports from Lighthouse results in multiple output formats.
/**
* Generate formatted report from Lighthouse results
* @param result - Lighthouse result or flow result to format
* @param format - Output format (html, json, csv)
* @returns Generated report as string
*/
function generateReport(
result: LH.Result | LH.FlowResult,
format?: LH.OutputMode
): string;Usage Examples:
import lighthouse, { generateReport } from 'lighthouse';
// Run audit and generate reports
const runnerResult = await lighthouse('https://example.com', {
port: chrome.port,
});
// Generate HTML report (default)
const htmlReport = generateReport(runnerResult.lhr);
console.log('HTML report length:', htmlReport.length);
// Generate JSON report
const jsonReport = generateReport(runnerResult.lhr, 'json');
const parsed = JSON.parse(jsonReport);
console.log('Performance score:', parsed.categories.performance.score);
// Generate CSV report
const csvReport = generateReport(runnerResult.lhr, 'csv');
console.log('CSV report:', csvReport);Generate reports specifically for user flow results with multi-step analysis.
import { startFlow, generateReport } from 'lighthouse';
const flow = await startFlow(page, {name: 'User Journey'});
await flow.navigate('https://example.com');
await flow.startTimespan();
// ... user interactions
await flow.endTimespan();
const flowResult = await flow.createFlowResult();
// Generate flow report (HTML format optimized for flows)
const flowHtmlReport = generateReport(flowResult, 'html');
// Generate flow JSON report
const flowJsonReport = generateReport(flowResult, 'json');File Output:
import fs from 'fs';
import lighthouse, { generateReport } from 'lighthouse';
const runnerResult = await lighthouse('https://example.com', {
port: chrome.port,
output: ['html', 'json'], // Generate multiple formats
outputPath: './lighthouse-report', // Base output path
});
// Reports are automatically saved when outputPath is provided
// Files: lighthouse-report.html, lighthouse-report.json
// Manual saving with custom names
const htmlReport = generateReport(runnerResult.lhr, 'html');
fs.writeFileSync('./custom-report.html', htmlReport);
const jsonReport = generateReport(runnerResult.lhr, 'json');
fs.writeFileSync('./custom-report.json', jsonReport);Extract Key Metrics:
const runnerResult = await lighthouse('https://example.com');
const jsonReport = generateReport(runnerResult.lhr, 'json');
const lhr = JSON.parse(jsonReport);
// Extract performance metrics
const metrics = {
performanceScore: lhr.categories.performance.score * 100,
fcp: lhr.audits['first-contentful-paint'].numericValue,
lcp: lhr.audits['largest-contentful-paint'].numericValue,
cls: lhr.audits['cumulative-layout-shift'].numericValue,
tbt: lhr.audits['total-blocking-time'].numericValue,
si: lhr.audits['speed-index'].numericValue,
};
console.log('Performance Metrics:', metrics);Extract Audit Details:
const jsonReport = generateReport(runnerResult.lhr, 'json');
const lhr = JSON.parse(jsonReport);
// Get failed audits
const failedAudits = Object.entries(lhr.audits)
.filter(([id, audit]) => audit.score !== null && audit.score < 1)
.map(([id, audit]) => ({
id,
title: audit.title,
description: audit.description,
score: audit.score,
displayValue: audit.displayValue,
}));
console.log('Failed audits:', failedAudits);The HTML format creates an interactive, comprehensive report with visualizations.
// HTML report features:
// - Interactive performance timeline
// - Expandable audit details
// - Opportunity recommendations
// - Diagnostic information
// - Screenshot and filmstrip view
// - Treemap for bundle analysis
const htmlReport = generateReport(result, 'html');
// Returns: Complete HTML document with embedded CSS/JSHTML Report Characteristics:
The JSON format provides machine-readable results for programmatic analysis.
// JSON report structure:
interface LH.Result {
lhr: LH.LighthouseResult; // Complete audit results
artifacts?: LH.Artifacts; // Raw collected data
report: string; // HTML report string
}
const jsonReport = generateReport(result, 'json');
// Returns: Stringified JSON with complete audit dataJSON Report Structure:
{
"audits": { // Individual audit results
"first-contentful-paint": {
"id": "first-contentful-paint",
"title": "First Contentful Paint",
"score": 0.99,
"numericValue": 1234,
"displayValue": "1.2 s"
}
},
"categories": { // Category scores
"performance": {
"id": "performance",
"title": "Performance",
"score": 0.95,
"auditRefs": [...]
}
},
"configSettings": {...}, // Configuration used
"environment": {...}, // Test environment info
"fetchTime": "2023-...", // Timestamp
"finalUrl": "https://...", // Final URL after redirects
"timing": {...} // Performance timing data
}The CSV format provides spreadsheet-compatible tabular data.
const csvReport = generateReport(result, 'csv');
// Returns: CSV string with audit results in tabular formatCSV Report Structure:
While Lighthouse doesn't provide direct template customization, you can post-process the JSON output:
const jsonReport = generateReport(runnerResult.lhr, 'json');
const lhr = JSON.parse(jsonReport);
// Create custom summary report
const customReport = {
url: lhr.finalUrl,
timestamp: lhr.fetchTime,
scores: {
performance: lhr.categories.performance.score * 100,
accessibility: lhr.categories.accessibility.score * 100,
bestPractices: lhr.categories['best-practices'].score * 100,
seo: lhr.categories.seo.score * 100,
},
coreWebVitals: {
lcp: lhr.audits['largest-contentful-paint'].displayValue,
fid: lhr.audits['max-potential-fid']?.displayValue || 'N/A',
cls: lhr.audits['cumulative-layout-shift'].displayValue,
},
opportunities: Object.values(lhr.audits)
.filter(audit => audit.details && audit.details.type === 'opportunity')
.map(audit => ({
title: audit.title,
savings: audit.details.overallSavingsMs,
description: audit.description,
})),
};
console.log('Custom report:', JSON.stringify(customReport, null, 2));const urls = [
'https://example.com',
'https://example.com/about',
'https://example.com/contact',
];
const reports = [];
for (const url of urls) {
const runnerResult = await lighthouse(url, {port: chrome.port});
const jsonReport = generateReport(runnerResult.lhr, 'json');
reports.push({
url,
timestamp: new Date().toISOString(),
report: JSON.parse(jsonReport),
});
}
// Generate combined summary
const summary = reports.map(({url, report}) => ({
url,
performance: report.categories.performance.score * 100,
accessibility: report.categories.accessibility.score * 100,
bestPractices: report.categories['best-practices'].score * 100,
seo: report.categories.seo.score * 100,
}));
console.table(summary);// Example for CI/CD pipeline
import lighthouse, { generateReport } from 'lighthouse';
import fs from 'fs';
async function auditForCI(url, thresholds = {}) {
const runnerResult = await lighthouse(url, {
port: chrome.port,
output: 'json',
throttlingMethod: 'simulate',
});
const jsonReport = generateReport(runnerResult.lhr, 'json');
const lhr = JSON.parse(jsonReport);
// Check against thresholds
const scores = {
performance: lhr.categories.performance.score * 100,
accessibility: lhr.categories.accessibility.score * 100,
bestPractices: lhr.categories['best-practices'].score * 100,
seo: lhr.categories.seo.score * 100,
};
const failures = Object.entries(thresholds)
.filter(([category, threshold]) => scores[category] < threshold)
.map(([category, threshold]) =>
`${category}: ${scores[category]} < ${threshold}`
);
// Save report for artifacts
fs.writeFileSync('./lighthouse-ci-report.json', jsonReport);
if (failures.length > 0) {
throw new Error(`Performance thresholds failed: ${failures.join(', ')}`);
}
return scores;
}
// Usage in CI
try {
const scores = await auditForCI('https://staging.example.com', {
performance: 90,
accessibility: 95,
bestPractices: 90,
seo: 95,
});
console.log('All thresholds passed:', scores);
} catch (error) {
console.error('CI audit failed:', error.message);
process.exit(1);
}// Example for sending results to monitoring system
async function sendToMonitoring(url) {
const runnerResult = await lighthouse(url);
const jsonReport = generateReport(runnerResult.lhr, 'json');
const lhr = JSON.parse(jsonReport);
const metrics = {
timestamp: Date.now(),
url: lhr.finalUrl,
performance_score: lhr.categories.performance.score,
fcp: lhr.audits['first-contentful-paint'].numericValue,
lcp: lhr.audits['largest-contentful-paint'].numericValue,
cls: lhr.audits['cumulative-layout-shift'].numericValue,
tbt: lhr.audits['total-blocking-time'].numericValue,
};
// Send to your monitoring system
await fetch('https://monitoring.example.com/api/lighthouse', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(metrics),
});
return metrics;
}try {
const runnerResult = await lighthouse('https://example.com');
// Check for runtime errors before generating report
if (runnerResult.lhr.runtimeError) {
console.error('Lighthouse runtime error:', runnerResult.lhr.runtimeError);
return null;
}
const htmlReport = generateReport(runnerResult.lhr, 'html');
const jsonReport = generateReport(runnerResult.lhr, 'json');
return { htmlReport, jsonReport };
} catch (error) {
console.error('Report generation failed:', error.message);
throw error;
}