pagespeed-quest 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,8 +24,9 @@ export class Dependency {
24
24
  await execa(lighthousePath, args, { stdout: 'inherit', stderr: 'inherit' });
25
25
  }
26
26
  async executeLoadshow(args) {
27
- const loadshowPath = process.env.LOADSHOW_PATH || './node_modules/.bin/loadshow';
27
+ const binaryName = process.platform === 'win32' ? 'loadshow.exe' : 'loadshow';
28
+ const loadshowPath = process.env.LOADSHOW_PATH || `./bin/${binaryName}`;
28
29
  await execa(loadshowPath, args, { stdout: 'inherit', stderr: 'inherit' });
29
30
  }
30
31
  }
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBlbmRlbmN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sR0FBRyxNQUFNLGFBQWEsQ0FBQTtBQUU3QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQzdCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUl2QixNQUFNLE9BQU8sVUFBVTtJQUNyQixNQUFNLENBQWM7SUFFcEI7UUFDRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNqQixLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksTUFBTTtZQUN0QyxTQUFTLEVBQUU7Z0JBQ1QsTUFBTSxFQUFFLGFBQWE7Z0JBQ3JCLE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxNQUFNLEVBQUUsY0FBYztvQkFDdEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7aUJBQ3ZGO2FBQ0Y7U0FDRixDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFlO1FBQzFCLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUMvQyxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQWM7UUFDcEMsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksZ0NBQWdDLENBQUE7UUFDdEYsTUFBTSxLQUFLLENBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUE7SUFDN0UsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBYztRQUNsQyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsSUFBSSw4QkFBOEIsQ0FBQTtRQUNoRixNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUMzRSxDQUFDO0NBQ0YifQ==
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBlbmRlbmN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sR0FBRyxNQUFNLGFBQWEsQ0FBQTtBQUU3QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQzdCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUl2QixNQUFNLE9BQU8sVUFBVTtJQUNyQixNQUFNLENBQWM7SUFFcEI7UUFDRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNqQixLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksTUFBTTtZQUN0QyxTQUFTLEVBQUU7Z0JBQ1QsTUFBTSxFQUFFLGFBQWE7Z0JBQ3JCLE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxNQUFNLEVBQUUsY0FBYztvQkFDdEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7aUJBQ3ZGO2FBQ0Y7U0FDRixDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFlO1FBQzFCLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUMvQyxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQWM7UUFDcEMsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksZ0NBQWdDLENBQUE7UUFDdEYsTUFBTSxLQUFLLENBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUE7SUFDN0UsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBYztRQUNsQyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUE7UUFDN0UsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksU0FBUyxVQUFVLEVBQUUsQ0FBQTtRQUN2RSxNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUMzRSxDQUFDO0NBQ0YifQ==
@@ -0,0 +1,32 @@
1
+ import { DependencyInterface } from './types.js';
2
+ /**
3
+ * Lighthouse audit result structure
4
+ */
5
+ export interface LighthouseAudit {
6
+ id: string;
7
+ title: string;
8
+ score: number | null;
9
+ numericValue?: number;
10
+ displayValue?: string;
11
+ }
12
+ /**
13
+ * Lighthouse JSON report structure (partial)
14
+ */
15
+ export interface LighthouseReport {
16
+ categories: {
17
+ performance: {
18
+ id: string;
19
+ title: string;
20
+ score: number | null;
21
+ };
22
+ };
23
+ audits: Record<string, LighthouseAudit>;
24
+ }
25
+ export interface GenerateLighthouseSummaryInput {
26
+ jsonPath: string;
27
+ outputPath: string;
28
+ }
29
+ /**
30
+ * Generates a Markdown summary from a Lighthouse JSON report
31
+ */
32
+ export declare function generateLighthouseSummary(opts: GenerateLighthouseSummaryInput, dependency: Pick<DependencyInterface, 'logger' | 'mkdirp'>): Promise<void>;
@@ -0,0 +1,80 @@
1
+ import fs from 'fs/promises';
2
+ import Path from 'path';
3
+ /**
4
+ * Performance metrics to extract from Lighthouse report
5
+ * Weights are based on Lighthouse v10+ scoring
6
+ */
7
+ const PERFORMANCE_METRICS = [
8
+ { id: 'first-contentful-paint', abbr: 'FCP', unit: 'ms', weight: 0.1 },
9
+ { id: 'largest-contentful-paint', abbr: 'LCP', unit: 'ms', weight: 0.25 },
10
+ { id: 'total-blocking-time', abbr: 'TBT', unit: 'ms', weight: 0.3 },
11
+ { id: 'cumulative-layout-shift', abbr: 'CLS', unit: '', weight: 0.25 },
12
+ { id: 'speed-index', abbr: 'SI', unit: 'ms', weight: 0.1 },
13
+ ];
14
+ /**
15
+ * Formats a score as a percentage integer
16
+ */
17
+ function formatScore(score) {
18
+ if (score === null)
19
+ return 'N/A';
20
+ return `${Math.round(score * 100)}`;
21
+ }
22
+ /**
23
+ * Formats a numeric value in milliseconds (rounded to integer)
24
+ * For CLS, returns the raw value with 3 decimal places
25
+ */
26
+ function formatValue(numericValue, unit) {
27
+ if (numericValue === undefined)
28
+ return 'N/A';
29
+ if (unit === '') {
30
+ // CLS - no unit, show decimal value
31
+ return numericValue.toFixed(3);
32
+ }
33
+ // Time-based metrics - round to integer ms
34
+ return `${Math.round(numericValue)} ${unit}`;
35
+ }
36
+ /**
37
+ * Generates a Markdown summary from a Lighthouse JSON report
38
+ */
39
+ export async function generateLighthouseSummary(opts, dependency) {
40
+ // Read and parse the Lighthouse JSON report
41
+ const jsonContent = await fs.readFile(opts.jsonPath, 'utf-8');
42
+ const report = JSON.parse(jsonContent);
43
+ // Extract overall performance score
44
+ const overallScore = report.categories?.performance?.score;
45
+ // Build the Markdown content
46
+ const lines = [];
47
+ lines.push('# Lighthouse Performance Summary');
48
+ lines.push('');
49
+ // Section 1: Metric Values
50
+ lines.push('## Metrics');
51
+ lines.push('');
52
+ for (const metric of PERFORMANCE_METRICS) {
53
+ const audit = report.audits[metric.id];
54
+ if (audit) {
55
+ const value = formatValue(audit.numericValue, metric.unit);
56
+ lines.push(`- ${metric.abbr} ${value}`);
57
+ }
58
+ }
59
+ lines.push('');
60
+ // Section 2: Scores
61
+ lines.push('## Scores');
62
+ lines.push('');
63
+ lines.push(`- Overall ${formatScore(overallScore)}`);
64
+ for (const metric of PERFORMANCE_METRICS) {
65
+ const audit = report.audits[metric.id];
66
+ if (audit) {
67
+ const score = formatScore(audit.score);
68
+ const weight = `x${metric.weight.toFixed(2)}`;
69
+ lines.push(`- ${metric.abbr} ${score} ${weight}`);
70
+ }
71
+ }
72
+ lines.push('');
73
+ // Ensure output directory exists
74
+ const outputDir = Path.dirname(opts.outputPath);
75
+ await dependency.mkdirp(outputDir);
76
+ // Write the summary file
77
+ await fs.writeFile(opts.outputPath, lines.join('\n'), 'utf-8');
78
+ dependency.logger?.info(`Lighthouse summary saved to ${opts.outputPath}`);
79
+ }
80
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS1zdW1tYXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2xpZ2h0aG91c2Utc3VtbWFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBNkJ2Qjs7O0dBR0c7QUFDSCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLEVBQUUsRUFBRSxFQUFFLHdCQUF3QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLDBCQUEwQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3pFLEVBQUUsRUFBRSxFQUFFLHFCQUFxQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ25FLEVBQUUsRUFBRSxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRTtDQUMzRCxDQUFBO0FBT0Q7O0dBRUc7QUFDSCxTQUFTLFdBQVcsQ0FBQyxLQUFvQjtJQUN2QyxJQUFJLEtBQUssS0FBSyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUE7SUFDaEMsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUE7QUFDckMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsV0FBVyxDQUFDLFlBQWdDLEVBQUUs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
@@ -1,5 +1,6 @@
1
1
  import Path from 'path';
2
2
  import { captureLighthouseDigest } from './lighthouse-digest.js';
3
+ import { generateLighthouseSummary } from './lighthouse-summary.js';
3
4
  export async function execLighthouse(opts, dependency) {
4
5
  const artifactsDir = opts.artifactsDir || './artifacts';
5
6
  await dependency.mkdirp(artifactsDir);
@@ -43,5 +44,19 @@ export async function execLighthouse(opts, dependency) {
43
44
  dependency.logger?.warn(`Failed to capture Lighthouse score and metrics: ${error}`);
44
45
  }
45
46
  }
47
+ // Generate summary markdown
48
+ if (opts.artifactsDir) {
49
+ const jsonPath = `${outputPath}.report.json`;
50
+ const summaryPath = Path.join(artifactsDir, 'summary.md');
51
+ try {
52
+ await generateLighthouseSummary({
53
+ jsonPath,
54
+ outputPath: summaryPath,
55
+ }, dependency);
56
+ }
57
+ catch (error) {
58
+ dependency.logger?.warn(`Failed to generate Lighthouse summary: ${error}`);
59
+ }
60
+ }
46
61
  }
47
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9saWdodGhvdXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUV2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQWNoRSxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBeUIsRUFDekIsVUFBZ0Y7SUFFaEYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxhQUFhLENBQUE7SUFDdkQsTUFBTSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRXJDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFBO0lBQzlDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFBO0lBQ3hELE1BQU0sSUFBSSxHQUFhO1FBQ3JCLElBQUksQ0FBQyxHQUFHO1FBQ1IsZUFBZTtRQUNmLG9CQUFvQjtRQUNwQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLCtCQUErQjtRQUMvQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLDRDQUE0QztRQUM1Qyw0QkFBNEIsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDeEUsNkRBQTZEO1FBQzdELHNCQUFzQjtRQUN0QiwrQkFBK0I7UUFDL0IsdUNBQXVDO1FBQ3ZDLHFDQUFxQztRQUNyQyxzQ0FBc0M7S0FDdkMsQ0FBQTtJQUVELElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBRWhELE1BQU0sV0FBVyxHQUFhLENBQUMsNkJBQTZCLEVBQUUsbUNBQW1DLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQ2xILElBQUksSUFBSSxDQUFDLFFBQVE7UUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBRXRELElBQUksSUFBSSxDQUFDLElBQUk7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBRWxDLE1BQU0sVUFBVSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBRXhDLG9EQUFvRDtJQUNwRCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsS0FBSyxLQUFLLEVBQUU7UUFDekMsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSx1QkFBdUIsQ0FBQyxDQUFBO1FBRW5FLElBQUk7WUFDRixNQUFNLHVCQUF1QixDQUMzQjtnQkFDRSxRQUFRO2dCQUNSLFVBQVUsRUFBRSxVQUFVO2FBQ3ZCLEVBQ0QsVUFBVSxDQUNYLENBQUE7U0FDRjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsVUFBVSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsbURBQW1ELEtBQUssRUFBRSxDQUFDLENBQUE7U0FDcEY7S0FDRjtBQUNILENBQUMifQ==
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9saWdodGhvdXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUV2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUNoRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQTtBQWNuRSxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBeUIsRUFDekIsVUFBZ0Y7SUFFaEYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxhQUFhLENBQUE7SUFDdkQsTUFBTSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRXJDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFBO0lBQzlDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFBO0lBQ3hELE1BQU0sSUFBSSxHQUFhO1FBQ3JCLElBQUksQ0FBQyxHQUFHO1FBQ1IsZUFBZTtRQUNmLG9CQUFvQjtRQUNwQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLCtCQUErQjtRQUMvQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLDRDQUE0QztRQUM1Qyw0QkFBNEIsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDeEUsNkRBQTZEO1FBQzdELHNCQUFzQjtRQUN0QiwrQkFBK0I7UUFDL0IsdUNBQXVDO1FBQ3ZDLHFDQUFxQztRQUNyQyxzQ0FBc0M7S0FDdkMsQ0FBQTtJQUVELElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBRWhELE1BQU0sV0FBVyxHQUFhLENBQUMsNkJBQTZCLEVBQUUsbUNBQW1DLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQ2xILElBQUksSUFBSSxDQUFDLFFBQVE7UUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBRXRELElBQUksSUFBSSxDQUFDLElBQUk7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBRWxDLE1BQU0sVUFBVSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBRXhDLG9EQUFvRDtJQUNwRCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsS0FBSyxLQUFLLEVBQUU7UUFDekMsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSx1QkFBdUIsQ0FBQyxDQUFBO1FBRW5FLElBQUk7WUFDRixNQUFNLHVCQUF1QixDQUMzQjtnQkFDRSxRQUFRO2dCQUNSLFVBQVUsRUFBRSxVQUFVO2FBQ3ZCLEVBQ0QsVUFBVSxDQUNYLENBQUE7U0FDRjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsVUFBVSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsbURBQW1ELEtBQUssRUFBRSxDQUFDLENBQUE7U0FDcEY7S0FDRjtJQUVELDRCQUE0QjtJQUM1QixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7UUFDckIsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUV6RCxJQUFJO1lBQ0YsTUFBTSx5QkFBeUIsQ0FDN0I7Z0JBQ0UsUUFBUTtnQkFDUixVQUFVLEVBQUUsV0FBVzthQUN4QixFQUNELFVBQVUsQ0FDWCxDQUFBO1NBQ0Y7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLDBDQUEwQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1NBQzNFO0tBQ0Y7QUFDSCxDQUFDIn0=
@@ -8,12 +8,14 @@ export interface ExecLoadshowInput {
8
8
  credit?: string;
9
9
  }
10
10
  export interface ExecLoadshowSpec {
11
+ preset?: 'desktop' | 'mobile';
11
12
  viewportWidth?: number;
12
13
  columns?: number;
13
14
  cpuThrottling?: number;
14
- timeoutMs?: number;
15
- userAgent?: string;
15
+ timeoutSec?: number;
16
16
  proxyPort?: number;
17
17
  credit?: string;
18
+ debugDir?: string;
19
+ outputSummary?: string;
18
20
  }
19
21
  export declare function execLoadshow(input: ExecLoadshowInput, dependency: Pick<DependencyInterface, 'mkdirp' | 'executeLoadshow'>): Promise<void>;
package/build/loadshow.js CHANGED
@@ -1,54 +1,62 @@
1
1
  import Path from 'path';
2
- import { defaultConfig, desktopConfig } from 'lighthouse';
3
2
  function execSpecToCommandArgs(spec) {
4
3
  const args = [];
4
+ // preset
5
+ if (spec.preset !== undefined)
6
+ args.push('--preset', spec.preset);
5
7
  // layout
6
8
  if (spec.columns !== undefined)
7
- args.push('-u', `layout.columns=${spec.columns}`);
8
- // recording
9
+ args.push('--columns', String(spec.columns));
10
+ // browser settings
9
11
  if (spec.viewportWidth !== undefined)
10
- args.push('-u', `recording.viewportWidth=${spec.viewportWidth}`);
12
+ args.push('--viewport-width', String(spec.viewportWidth));
11
13
  if (spec.cpuThrottling !== undefined)
12
- args.push('-u', `recording.cpuThrottling=${spec.cpuThrottling}`);
13
- if (spec.timeoutMs !== undefined)
14
- args.push('-u', `recording.timeoutMs=${spec.timeoutMs}`);
15
- if (spec.userAgent !== undefined)
16
- args.push('-u', `recording.headers.User-Agent=${spec.userAgent}`);
17
- // recording.puppeteer
18
- const chromeArgs = ['--ignore-certificate-errors'];
14
+ args.push('--cpu-throttling', String(spec.cpuThrottling));
15
+ // timeout
16
+ if (spec.timeoutSec !== undefined)
17
+ args.push('--timeout-sec', String(spec.timeoutSec));
18
+ // proxy settings
19
19
  if (spec.proxyPort !== undefined) {
20
- chromeArgs.push(`--proxy-server=http://localhost:${spec.proxyPort}`);
20
+ args.push('--proxy-server', `http://localhost:${spec.proxyPort}`);
21
+ args.push('--ignore-https-errors');
21
22
  }
22
- args.push('-u', 'recording.puppeteer.args=' + chromeArgs.join(','));
23
23
  // credit
24
24
  if (spec.credit)
25
- args.push('-u', `banner.vars.credit=${spec.credit}`);
25
+ args.push('--credit', spec.credit);
26
+ // debug directory
27
+ if (spec.debugDir)
28
+ args.push('--debug-dir', spec.debugDir);
29
+ // output summary
30
+ if (spec.outputSummary)
31
+ args.push('--output-summary', spec.outputSummary);
26
32
  return args;
27
33
  }
28
34
  export async function execLoadshow(input, dependency) {
29
35
  const artifactsDir = input.artifactsDir || './artifacts';
30
36
  const loadshowDir = Path.join(artifactsDir, 'loadshow');
31
37
  const outputPath = Path.join(artifactsDir, 'loadshow.mp4');
38
+ const summaryPath = Path.join(loadshowDir, 'summary.md');
32
39
  await dependency.mkdirp(loadshowDir);
33
40
  // By form factor
34
- const lighthouseByDevice = input.deviceType === 'desktop' ? desktopConfig : defaultConfig;
41
+ const preset = input.deviceType === 'desktop' ? 'desktop' : 'mobile';
35
42
  const customByDevice = input.deviceType === 'desktop' ? { columns: 2 } : { columns: 3 };
43
+ // Convert timeout from milliseconds to seconds
44
+ const timeoutSec = Math.ceil(input.timeout / 1000);
36
45
  // Basic spec
37
- const userAgent = lighthouseByDevice.settings?.emulatedUserAgent;
38
46
  const spec = {
47
+ preset,
39
48
  proxyPort: input.proxyPort,
40
49
  columns: customByDevice.columns,
41
- viewportWidth: lighthouseByDevice.settings?.screenEmulation?.width,
42
- cpuThrottling: lighthouseByDevice.settings?.throttling?.cpuSlowdownMultiplier,
43
- userAgent: typeof userAgent === 'string' ? userAgent : undefined,
44
- timeoutMs: input.timeout,
50
+ timeoutSec,
45
51
  credit: input.credit,
52
+ debugDir: loadshowDir,
53
+ outputSummary: summaryPath,
46
54
  };
47
55
  const args = [];
48
56
  args.push('record');
49
- args.push('-a', loadshowDir);
50
57
  args.push(...execSpecToCommandArgs(spec));
51
- args.push(input.url, outputPath);
58
+ args.push('--output', outputPath);
59
+ args.push(input.url);
52
60
  await dependency.executeLoadshow(args);
53
61
  }
54
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZHNob3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbG9hZHNob3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRXZCLE9BQU8sRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBdUJ6RCxTQUFTLHFCQUFxQixDQUFDLElBQXNCO0lBQ25ELE1BQU0sSUFBSSxHQUFhLEVBQUUsQ0FBQTtJQUV6QixTQUFTO0lBQ1QsSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLFNBQVM7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxrQkFBa0IsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFFakYsWUFBWTtJQUNaLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsMkJBQTJCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFBO0lBQ3RHLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsMkJBQTJCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFBO0lBQ3RHLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQzFGLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsZ0NBQWdDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBRW5HLHNCQUFzQjtJQUN0QixNQUFNLFVBQVUsR0FBYSxDQUFDLDZCQUE2QixDQUFDLENBQUE7SUFDNUQsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMs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
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZHNob3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbG9hZHNob3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBeUJ2QixTQUFTLHFCQUFxQixDQUFDLElBQXNCO0lBQ25ELE1BQU0sSUFBSSxHQUFhLEVBQUUsQ0FBQTtJQUV6QixTQUFTO0lBQ1QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFakUsU0FBUztJQUNULElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFBO0lBRTVFLG1CQUFtQjtJQUNuQixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssU0FBUztRQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFBO0lBQy9GLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUE7SUFFL0YsVUFBVTtJQUNWLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFBO0lBRXRGLGlCQUFpQjtJQUNqQixJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFO1FBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsb0JBQW9CLElBQUksQ0FBQyxTQUFTLEVB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pagespeed-quest",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "description": "A framework for efficient web front-end speed improvement",
6
6
  "main": "build/index.js",
@@ -46,7 +46,8 @@
46
46
  "prepare-release": "run-s reset-hard test cov:check doc:html version doc:publish",
47
47
  "adhoc": "yarn build && node build/adhoc.js",
48
48
  "command": "yarn build && node build/command.js",
49
- "prepublishOnly": "yarn build"
49
+ "prepublishOnly": "yarn build",
50
+ "postinstall": "node scripts/postinstall.js"
50
51
  },
51
52
  "engines": {
52
53
  "node": ">=18"
@@ -57,7 +58,6 @@
57
58
  "iconv-lite": "^0.6.3",
58
59
  "jschardet": "^3.0.0",
59
60
  "lighthouse": "^12.2.1",
60
- "loadshow": "1.2.0",
61
61
  "node-html-to-image": "^5.0.0",
62
62
  "node-watch": "^0.7.4",
63
63
  "pino": "^9.4.0",
@@ -93,6 +93,7 @@
93
93
  },
94
94
  "files": [
95
95
  "build",
96
+ "scripts",
96
97
  "!**/*.spec.*",
97
98
  "!**/*.json",
98
99
  "CHANGELOG.md",
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createWriteStream, mkdirSync, chmodSync, existsSync, unlinkSync } from 'fs'
4
+ import { pipeline } from 'stream/promises'
5
+ import { createGunzip } from 'zlib'
6
+ import { extract } from 'tar'
7
+ import { fileURLToPath } from 'url'
8
+ import { dirname, join } from 'path'
9
+
10
+ const __filename = fileURLToPath(import.meta.url)
11
+ const __dirname = dirname(__filename)
12
+
13
+ const LOADSHOW_VERSION = 'v1.3.0'
14
+ const REPO = 'ideamans/go-loadshow'
15
+
16
+ function getPlatformInfo() {
17
+ const platform = process.platform
18
+ const arch = process.arch
19
+
20
+ if (platform === 'darwin' && arch === 'arm64') {
21
+ return { os: 'darwin', arch: 'arm64', ext: 'tar.gz' }
22
+ } else if (platform === 'darwin' && arch === 'x64') {
23
+ // macOS x64 is not available, fall back to arm64 (Rosetta 2)
24
+ return { os: 'darwin', arch: 'arm64', ext: 'tar.gz' }
25
+ } else if (platform === 'linux' && arch === 'x64') {
26
+ return { os: 'linux', arch: 'amd64', ext: 'tar.gz' }
27
+ } else if (platform === 'linux' && arch === 'arm64') {
28
+ return { os: 'linux', arch: 'arm64', ext: 'tar.gz' }
29
+ } else if (platform === 'win32' && arch === 'x64') {
30
+ return { os: 'windows', arch: 'amd64', ext: 'zip' }
31
+ } else {
32
+ throw new Error(`Unsupported platform: ${platform} ${arch}`)
33
+ }
34
+ }
35
+
36
+ async function downloadFile(url, destPath) {
37
+ const response = await fetch(url, { redirect: 'follow' })
38
+ if (!response.ok) {
39
+ throw new Error(`Failed to download: ${response.status} ${response.statusText}`)
40
+ }
41
+ const fileStream = createWriteStream(destPath)
42
+ await pipeline(response.body, fileStream)
43
+ }
44
+
45
+ async function extractTarGz(archivePath, destDir) {
46
+ const { execSync } = await import('child_process')
47
+ execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: 'inherit' })
48
+ }
49
+
50
+ async function extractZip(archivePath, destDir) {
51
+ const { execSync } = await import('child_process')
52
+ execSync(`unzip -o "${archivePath}" -d "${destDir}"`, { stdio: 'inherit' })
53
+ }
54
+
55
+ async function main() {
56
+ const binDir = join(__dirname, '..', 'bin')
57
+ const platformInfo = getPlatformInfo()
58
+
59
+ const assetName = `loadshow_${LOADSHOW_VERSION}_${platformInfo.os}_${platformInfo.arch}.${platformInfo.ext}`
60
+ const downloadUrl = `https://github.com/${REPO}/releases/download/${LOADSHOW_VERSION}/${assetName}`
61
+
62
+ console.log(`Downloading go-loadshow ${LOADSHOW_VERSION} for ${platformInfo.os}/${platformInfo.arch}...`)
63
+ console.log(`URL: ${downloadUrl}`)
64
+
65
+ // Create bin directory if not exists
66
+ if (!existsSync(binDir)) {
67
+ mkdirSync(binDir, { recursive: true })
68
+ }
69
+
70
+ const archivePath = join(binDir, assetName)
71
+ const binaryName = platformInfo.os === 'windows' ? 'loadshow.exe' : 'loadshow'
72
+ const binaryPath = join(binDir, binaryName)
73
+
74
+ // Download archive
75
+ await downloadFile(downloadUrl, archivePath)
76
+ console.log('Download complete. Extracting...')
77
+
78
+ // Extract archive
79
+ if (platformInfo.ext === 'tar.gz') {
80
+ await extractTarGz(archivePath, binDir)
81
+ } else {
82
+ await extractZip(archivePath, binDir)
83
+ }
84
+
85
+ // Make binary executable (Unix only)
86
+ if (platformInfo.os !== 'windows') {
87
+ chmodSync(binaryPath, 0o755)
88
+ }
89
+
90
+ // Clean up archive
91
+ unlinkSync(archivePath)
92
+
93
+ console.log(`go-loadshow installed successfully at ${binaryPath}`)
94
+ }
95
+
96
+ main().catch((err) => {
97
+ console.error('Failed to install go-loadshow:', err.message)
98
+ process.exit(1)
99
+ })