feat: implement automated Lighthouse CI testing for sitemap URLs with dedicated configuration and scripts.
This commit is contained in:
115
scripts/pagespeed-sitemap.ts
Normal file
115
scripts/pagespeed-sitemap.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import axios from 'axios';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { execSync } from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
/**
|
||||
* PageSpeed Test Script
|
||||
*
|
||||
* 1. Fetches sitemap.xml from the target URL
|
||||
* 2. Extracts all URLs
|
||||
* 3. Runs Lighthouse CI on those URLs
|
||||
*/
|
||||
|
||||
const targetUrl = process.argv[2] || process.env.NEXT_PUBLIC_BASE_URL || 'https://testing.klz-cables.com';
|
||||
const limit = process.env.PAGESPEED_LIMIT ? parseInt(process.env.PAGESPEED_LIMIT) : 20; // Default limit to avoid infinite runs
|
||||
const gatekeeperPassword = process.env.GATEKEEPER_PASSWORD || 'klz2026';
|
||||
|
||||
async function main() {
|
||||
console.log(`\n🚀 Starting PageSpeed test for: ${targetUrl}`);
|
||||
console.log(`📊 Limit: ${limit} pages\n`);
|
||||
|
||||
try {
|
||||
// 1. Fetch Sitemap
|
||||
const sitemapUrl = `${targetUrl.replace(/\/$/, '')}/sitemap.xml`;
|
||||
console.log(`📥 Fetching sitemap from ${sitemapUrl}...`);
|
||||
|
||||
// We might need to bypass gatekeeper for the sitemap fetch too
|
||||
const response = await axios.get(sitemapUrl, {
|
||||
headers: {
|
||||
'Cookie': `klz_gatekeeper_session=${gatekeeperPassword}`
|
||||
},
|
||||
validateStatus: (status) => status < 400
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data, { xmlMode: true });
|
||||
let urls = $('url loc').map((i, el) => $(el).text()).get();
|
||||
|
||||
// Cleanup and filter
|
||||
urls = [...new Set(urls)].filter(u => u.startsWith('http')).sort();
|
||||
|
||||
console.log(`✅ Found ${urls.length} URLs in sitemap.`);
|
||||
|
||||
if (urls.length === 0) {
|
||||
console.error('❌ No URLs found in sitemap. Is the site up?');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (urls.length > limit) {
|
||||
console.log(`⚠️ Too many pages (${urls.length}). Limiting to ${limit} representative pages.`);
|
||||
// Try to pick a variety: home, some products, some blog posts
|
||||
const home = urls.filter(u => u.endsWith('/de') || u.endsWith('/en') || u === targetUrl);
|
||||
const others = urls.filter(u => !home.includes(u));
|
||||
urls = [...home, ...others.slice(0, limit - home.length)];
|
||||
}
|
||||
|
||||
console.log(`🧪 Pages to be tested:`);
|
||||
urls.forEach(u => console.log(` - ${u}`));
|
||||
|
||||
// 2. Prepare LHCI command
|
||||
// We use --collect.url multiple times
|
||||
const urlArgs = urls.map(u => `--collect.url="${u}"`).join(' ');
|
||||
|
||||
// Handle authentication for staging/testing
|
||||
// Lighthouse can set cookies via --collect.settings.extraHeaders
|
||||
const extraHeaders = JSON.stringify({
|
||||
'Cookie': `klz_gatekeeper_session=${gatekeeperPassword}`
|
||||
});
|
||||
|
||||
console.log(`\n🏗️ Running Lighthouse CI...`);
|
||||
|
||||
// Using a more robust way to execute and capture output
|
||||
const lhciCommand = `npx lhci collect ${urlArgs} --collect.settings.chromeFlags='--no-sandbox --disable-setuid-sandbox' --collect.settings.extraHeaders='${extraHeaders}' && npx lhci assert && npx lhci upload`;
|
||||
|
||||
console.log(`💻 Executing LHCI...`);
|
||||
|
||||
try {
|
||||
const output = execSync(lhciCommand, {
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'inherit'] // Pipe stdout so we can parse it
|
||||
});
|
||||
|
||||
console.log(output);
|
||||
|
||||
// Extract report URL from LHCI output
|
||||
const reportMatch = output.match(/Sent to (https:\/\/storage\.googleapis\.com\/lighthouse-infrastructure\.appspot\.com\/reports\/[^\s]+)/);
|
||||
if (reportMatch && reportMatch[1]) {
|
||||
const reportUrl = reportMatch[1];
|
||||
console.log(`\n📊 Report URL: ${reportUrl}`);
|
||||
fs.writeFileSync('pagespeed-report-url.txt', reportUrl);
|
||||
}
|
||||
|
||||
} catch (err: any) {
|
||||
console.error('❌ LHCI execution failed.');
|
||||
if (err.stdout) console.log(err.stdout);
|
||||
if (err.stderr) console.error(err.stderr);
|
||||
throw err;
|
||||
}
|
||||
|
||||
console.log(`\n✨ PageSpeed tests completed successfully!`);
|
||||
|
||||
} catch (error: any) {
|
||||
console.error(`\n❌ Error during PageSpeed test:`);
|
||||
if (axios.isAxiosError(error)) {
|
||||
console.error(`Status: ${error.response?.status}`);
|
||||
console.error(`StatusText: ${error.response?.statusText}`);
|
||||
console.error(`URL: ${error.config?.url}`);
|
||||
} else {
|
||||
console.error(error.message);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user