feat: create MobilePerformanceMonitor base structure

This commit is contained in:
张翔
2026-03-05 15:21:29 +08:00
parent 858eb2efcf
commit 3f18618c84
-62
View File
@@ -1,6 +1,4 @@
import { Page } from '@playwright/test';
import lighthouse from 'lighthouse';
import * as chromeLauncher from 'chrome-launcher';
export interface CoreWebVitals {
FCP: number;
@@ -17,64 +15,4 @@ export interface LighthouseResult {
export class MobilePerformanceMonitor {
constructor(private page: Page) {}
async getCoreWebVitals(): Promise<CoreWebVitals> {
const vitals = await this.page.evaluate(() => {
return new Promise((resolve) => {
const metrics: any = {};
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'paint') {
if (entry.name === 'first-contentful-paint') {
metrics.FCP = entry.startTime;
}
} else if (entry.entryType === 'largest-contentful-paint') {
metrics.LCP = entry.startTime;
} else if (entry.entryType === 'layout-shift') {
if (!metrics.CLS) metrics.CLS = 0;
metrics.CLS += (entry as any).value;
}
}
});
observer.observe({ entryTypes: ['paint', 'largest-contentful-paint', 'layout-shift'] });
setTimeout(() => {
observer.disconnect();
resolve(metrics);
}, 5000);
});
});
return {
FCP: vitals.FCP || 0,
LCP: vitals.LCP || 0,
CLS: vitals.CLS || 0,
FID: 0,
TTI: 0,
};
}
async runLighthouseAudit(url: string): Promise<LighthouseResult> {
const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
const options = {
logLevel: 'info' as const,
output: 'json' as const,
onlyCategories: ['performance'],
port: chrome.port,
};
const runnerResult = await lighthouse(url, options);
await chrome.kill();
if (!runnerResult) {
throw new Error('Lighthouse audit failed');
}
return {
score: runnerResult.lhr.categories.performance.score * 100,
audits: runnerResult.lhr.audits,
};
}
}