Π§ΡΠΎ ΡΠ°ΠΊΠΎΠ΅ Lighthouse ΠΈ ΠΊΠ°ΠΊΠΈΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΠΎΠ½ ΠΈΠ·ΠΌΠ΅ΡΡΠ΅Ρ?
ΠΠΎΠ»Π½ΡΠΉ ΠΎΡΠ²Π΅Ρ
Lighthouse Π·Π°ΠΏΡΡΠΊΠ°Π΅Ρ ΡΡΡΠ°Π½ΠΈΡΡ Π² ΠΊΠΎΠ½ΡΡΠΎΠ»ΠΈΡΡΠ΅ΠΌΠΎΠΌ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠΈ ΠΈ ΡΠΎΠ±ΠΈΡΠ°Π΅Ρ ΠΌΠ΅ΡΡΠΈΠΊΠΈ:
# Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΠΈ Π·Π°ΠΏΡΡΠΊ ΡΠ΅ΡΠ΅Π· CLI
npm install -g lighthouse
# ΠΠ°Π·ΠΎΠ²ΡΠΉ Π°ΡΠ΄ΠΈΡ
lighthouse https://example.com --output html --output-path report.html
# Π’ΠΎΠ»ΡΠΊΠΎ performance
lighthouse https://example.com --only-categories=performance
# ΠΠΎΠ±ΠΈΠ»ΡΠ½ΡΠΉ (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ) ΠΈ Π΄Π΅ΡΠΊΡΠΎΠΏΠ½ΡΠΉ ΡΠ΅ΠΆΠΈΠΌΡ
lighthouse https://example.com --preset=desktop
lighthouse https://example.com --preset=perf # ΡΡΠ΅Π·Π°Π½Π½ΡΠΉ, ΡΠΎΠ»ΡΠΊΠΎ performance
Performance-ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΠΈ ΠΈΡ Π²Π΅Ρ Π² ΠΎΠ±ΡΠ΅ΠΉ ΠΎΡΠ΅Π½ΠΊΠ΅ (Lighthouse 12):
ΠΠ΅ΡΡΠΈΠΊΠ° ΠΠ΅Ρ Π₯ΠΎΡΠΎΡΠΎ ΠΠ»ΠΎΡ
ΠΎ
---------------------------------------------------------
First Contentful Paint (FCP) 10% < 1.8s > 3.0s
Largest Contentful Paint (LCP) 25% < 2.5s > 4.0s
Total Blocking Time (TBT) 30% < 200ms > 600ms
Cumulative Layout Shift (CLS) 25% < 0.1 > 0.25
Speed Index (SI) 10% < 3.4s > 5.8s
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΠΉ Π·Π°ΠΏΡΡΠΊ ΠΈΠ· Node.js:
import lighthouse from 'lighthouse';
import puppeteer from 'puppeteer';
async function runAudit(url) {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
const result = await lighthouse(url, {
port: new URL(browser.wsEndpoint()).port,
output: 'json',
onlyCategories: ['performance'],
});
const { categories, audits } = result.lhr;
console.log(`Performance score: ${categories.performance.score * 100}`);
console.log(`FCP: ${audits['first-contentful-paint'].displayValue}`);
console.log(`LCP: ${audits['largest-contentful-paint'].displayValue}`);
console.log(`TBT: ${audits['total-blocking-time'].displayValue}`);
console.log(`CLS: ${audits['cumulative-layout-shift'].displayValue}`);
// ΠΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠ΅ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΠΈ
const opportunities = Object.values(audits).filter(
(a) => a.details?.type === 'opportunity' && a.details.overallSavingsMs > 0
);
for (const opp of opportunities) {
console.log(`${opp.title}: ΠΌΠΎΠΆΠ½ΠΎ ΡΡΠΊΠΎΠ½ΠΎΠΌΠΈΡΡ ${opp.details.overallSavingsMs} ms`);
}
await browser.close();
return result;
}
runAudit('https:// example.com');
ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Π² CI/CD:
// lighthouserc.js
export default {
ci: {
collect: {
url: ['http:// localhost:3000/', 'http:// localhost:3000/about'],
numberOfRuns: 3, // ΡΡΠ΅Π΄Π½Π΅Π΅ ΠΈΠ· ΡΡΡΡ
Π·Π°ΠΏΡΡΠΊΠΎΠ²
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'categories:accessibility': ['warn', { minScore: 0.95 }],
'first-contentful-paint': ['error', { maxNumericValue: 1800 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
},
},
},
};
# ΠΠ°ΠΏΡΡΠΊ Π² CI
npm install -g @lhci/cli
lhci autorun --config=lighthouserc.js
π Π Π΅Π°Π»ΡΠ½ΡΠ΅ ΠΊΠ΅ΠΉΡΡ
Π’ΠΈΠΏΠΈΡΠ½ΡΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΏΡΠΈ ΡΠ°Π±ΠΎΡΠ΅ Ρ Lighthouse:
// β Π‘ΡΠ°Π²Π½ΠΈΠ²Π°ΡΡ ΠΎΡΠ΅Π½ΠΊΠΈ ΠΌΠ΅ΠΆΠ΄Ρ Π·Π°ΠΏΡΡΠΊΠ°ΠΌΠΈ Π½Π°ΠΏΡΡΠΌΡΡ
// Lighthouse ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΡΠ°Π·Π½ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π·Π°ΠΏΡΡΠΊΠ΅ ΠΈΠ·-Π·Π° ΡΠ΅ΡΠΈ ΠΈ CPU
// β
ΠΠ΅Π»Π°ΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ Π·Π°ΠΏΡΡΠΊΠΎΠ² ΠΈ Π±ΡΠ°ΡΡ ΠΌΠ΅Π΄ΠΈΠ°Π½Ρ
// lighthouse --output json | jq '.audits["first-contentful-paint"].numericValue'
// ΠΠ°ΠΏΡΡΡΠΈΡΡ 5 ΡΠ°Π·, Π²Π·ΡΡΡ ΠΌΠ΅Π΄ΠΈΠ°Π½Ρ
// β ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ DevTools Lighthouse (Π±Π΅Π· throttling)
// DevTools ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΡΠΌΡΠ»ΠΈΡΡΠ΅Ρ ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΈ CPU
// β
Π’Π΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ Π² ΡΡΠ»ΠΎΠ²ΠΈΡΡ
, Π±Π»ΠΈΠ·ΠΊΠΈΡ
ΠΊ ΡΠ΅Π°Π»ΡΠ½ΡΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΠΌ
// PageSpeed Insights ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΠΈ Π»Π°Π±ΠΎΡΠ°ΡΠΎΡΠ½ΡΠ΅, ΠΈ ΠΏΠΎΠ»Π΅Π²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ (CrUX)
Π Π΅Π·ΡΠΌΠ΅
Lighthouse -- ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½Ρ Π°ΡΠ΄ΠΈΡΠ° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ ΠΎΡ Google. ΠΠ½ Π΄Π°ΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΠΈ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΠΈ, Π½ΠΎ Π²Π°ΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ½ΠΈΡΡ ΠΎ Π²Π°ΡΠΈΠ°ΡΠΈΠ²Π½ΠΎΡΡΠΈ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² ΠΌΠ΅ΠΆΠ΄Ρ Π·Π°ΠΏΡΡΠΊΠ°ΠΌΠΈ. ΠΠ»Ρ Π΄ΠΎΡΡΠΎΠ²Π΅ΡΠ½ΡΡ Π΄Π°Π½Π½ΡΡ Π½ΡΠΆΠ½ΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ Π·Π°ΠΏΡΡΠΊΠΎΠ² ΠΈ ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ Ρ ΠΏΠΎΠ»Π΅Π²ΡΠΌΠΈ ΠΌΠ΅ΡΡΠΈΠΊΠ°ΠΌΠΈ ΠΈΠ· CrUX. ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Π² CI ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Π΅Ρ ΡΠ΅Π³ΡΠ΅ΡΡΠΈΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ.