A Playwright teljesítménytesztek azt jelentik, hogy a Playwright böngészőautomatizációs keretrendszerével valódi Chromium példányban futtatunk mérési szkripteket, amelyek a web-vitals.js könyvtárat beinjektálva rögzítik a Core Web Vitals (LCP, INP, CLS) értékeit, majd a CI pipeline egy előre definiált regressziós költségvetéshez hasonlítja azokat. 2026-ban a Playwright 1.50+ verziója már natívan támogatja a Chrome DevTools Protocol throttling API-t, így a Lighthouse-tól független, gyorsabb és stabilabb szintetikus mérőrendszert lehet építeni néhány óra alatt.
A Playwright 1.50+ és a web-vitals.js v5 kombinációja lehetővé teszi az összes Core Web Vitals metrika (LCP, INP, CLS, TTFB, FCP) mérését egyetlen tesztfájlban, körülbelül 40 sor kóddal.
A Chrome DevTools Protocol (CDP) session throttling stabilabb és 3-4× gyorsabb, mint a Lighthouse CI teljes auditja. Regressziós tesztekhez ez az iparági alapértelmezés 2026-ban.
Az INP mérése szintetikusan nehéz, mert valódi felhasználói interakció kell hozzá. Playwrightban a page.click() és page.dispatchEvent() hívásokkal lehet szimulálni, majd a metrikát a onINP callbacken keresztül kiolvasni.
A GitHub Actions matrix-tal érdemes párhuzamosan három futtatást indítani ugyanarra az URL-re, és a medián értéket használni, mert egyetlen szintetikus futás varianciája elérheti a 15-25%-ot.
A regressziós költségvetést p75-alapú küszöbként definiáld (LCP < 2500 ms, INP < 200 ms, CLS < 0.1), és a PR-ekben csak akkor buktasd a buildet, ha a mérés ezen kívülre esik. Ne pedig fix delta alapján.
A Playwright nem helyettesíti a Real User Monitoringot. A szintetikus adatok kiegészítik a valós felhasználói mérésekből érkező p75 percentiliseket.
Miért Playwright a teljesítményteszthez 2026-ban?
A csapatok többsége évek óta Lighthouse CI-t használ regressziós teljesítménytesztekhez, de 2026-ra egyre világosabb, hogy a Lighthouse két területen gyengén teljesít: a mérés lassú (egy audit átlagosan 45-90 másodperc), és az INP metrikát nem tudja megbízhatóan szimulálni. A Playwright ezzel szemben másodpercek alatt végigfut egy oldalon, valódi interakciókat képes elvégezni, és Chromium-alapon a web-vitals.js hivatalos könyvtárához fér hozzá, amely pontosan ugyanazt az API-t használja, mint amit a Chrome UX Report ad vissza.
Az én tapasztalatom szerint (hat évet töltöttem egy nagy zeneszolgáltató Web Player csapatában, ahol a TTI-regressziós költségvetést birtokoltam) a Lighthouse CI kifejezetten problémás monorepókban, ahol egy PR több száz oldalt érint. Amikor 20-30 URL-re kell futtatni auditot, a build könnyen 40 percre nyúlik, és a fejlesztők egyszerűen kikapcsolják. Őszintén szólva, ezt már láttam háromszor. A Playwright ezt a nagyságrendet 8-12 percre csökkenti, mert nem hordozza magával a teljes Lighthouse audit súlyát, csak azt méri, amit valóban kérünk.
A második ok, ami miatt Playwright-re váltottam: a mérési szkript ugyanaz a nyelv és tooling, mint amit a csapat funkcionális E2E tesztekhez már használ. Nincs külön config, külön retry-logika, külön riporter. A perf teszt egy másik *.spec.ts fájl a tests/ mappában, a szokásos Playwright reporterrel.
Alapkörnyezet: Playwright 1.50 és web-vitals.js v5 telepítése
A 2026-os stabil verziók: Playwright 1.50+ (a CDP session API változtatásokkal), web-vitals.js v5.0+ (az új INP algoritmussal, amely a P98 leghosszabb interakciót veszi). A Node 20 LTS az elfogadott baseline. Kezdjük egy tiszta projekttel.
A playwright.config.ts minimális perf-oriented beállítása így néz ki:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './perf-tests',
timeout: 60_000,
fullyParallel: false, // szeriálisan futtatunk, hogy a CPU tiszta legyen
workers: 1,
retries: 0, // NE retryzz teljesítménytesztet, inkább mediánt vegyél
reporter: [['json', { outputFile: 'perf-results.json' }], ['list']],
use: {
...devices['Desktop Chrome'],
headless: true,
viewport: { width: 1366, height: 768 },
},
});
Két dolgot érdemes kiemelni. Az retries: 0 szándékos: teljesítménytesztet nem retryzünk automatikusan, mert az elrejti a valódi regressziókat. A workers: 1 pedig biztosítja, hogy két teszt nem osztozik CPU-n. Ha párhuzamosan futtatnád őket, a variancia a duplájára nőhet.
Hogyan mérjünk Core Web Vitals metrikákat Playwright-tel?
A központi ötlet: a Playwright egy Node-oldali kontextusban fut, a web-vitals.js viszont a böngészőben kell hogy éljen. Az addInitScript pontosan erre való, beinjektálja a könyvtárat még a page load előtt, és a window-ra tesz egy globális gyűjtőt.
import { test, expect, Page } from '@playwright/test';
import * as fs from 'fs';
const webVitalsScript = fs.readFileSync(
require.resolve('web-vitals/dist/web-vitals.iife.js'),
'utf-8'
);
async function measureCWV(page: Page, url: string) {
await page.addInitScript(webVitalsScript);
await page.addInitScript(() => {
(window as any).__cwv = {};
// @ts-ignore, web-vitals.js beinjektálva
webVitals.onLCP((m) => ((window as any).__cwv.LCP = m.value));
webVitals.onCLS((m) => ((window as any).__cwv.CLS = m.value));
webVitals.onINP((m) => ((window as any).__cwv.INP = m.value));
webVitals.onFCP((m) => ((window as any).__cwv.FCP = m.value));
webVitals.onTTFB((m) => ((window as any).__cwv.TTFB = m.value));
});
await page.goto(url, { waitUntil: 'networkidle' });
// Kényszerítsük ki a CLS és INP flush-ot: bezárjuk a láthatóságot
await page.evaluate(() => document.dispatchEvent(
new Event('visibilitychange')
));
await page.waitForTimeout(500);
return page.evaluate(() => (window as any).__cwv);
}
test('LCP a főoldalon 2500 ms alatt', async ({ page }) => {
const metrics = await measureCWV(page, 'https://example.com/');
console.log('CWV:', metrics);
expect(metrics.LCP).toBeLessThan(2500);
expect(metrics.CLS).toBeLessThan(0.1);
});
Egy fontos részlet, amit gyakran elfelejtenek: a visibilitychange esemény manuális kiváltása. A web-vitals.js csak akkor "flushöli" a végleges CLS és INP értéket, amikor a lap háttérbe kerül vagy bezáródik. Playwrightban ez sosem történik meg automatikusan, ezért a mérés előtt manuálisan kell triggerelni. Ha ezt kihagyod, hiányos metrikákat fogsz kapni, és órákig fogod keresni, hogy miért NaN a CLS. (Én kb. két és fél órát pazaroltam el pont ezen, még 2024-ben.)
Chrome DevTools Protocol throttling: hálózat és CPU
Egy dev laptop 32 GB RAM-mal és gigabites vezetékes hálózattal nem reprezentatív egyetlen felhasználó sem. A CI mérésnek szimulálnia kell egy mediánközeli mobil felhasználót. A Playwright a CDP session API-n keresztül férhet hozzá a Chromium alacsonyszintű throttling parancsaihoz, amelyeket a Lighthouse is használ.
A Lighthouse alapértelmezetten "Slow 4G" plusz 4× CPU slowdownt használ mobil auditokhoz. Ha a mérésed a CI-ben ugyanezekkel a paraméterekkel megy, az eredmények közvetlenül összehasonlíthatók egy Lighthouse futással. Ez fontos, mert így nem kell két baseline-t vezetned.
Hogyan mérjük az INP-t Playwrightban?
Az INP (Interaction to Next Paint) mérése szintetikusan azért nehéz, mert kell hozzá valódi felhasználói interakció: kattintás, gombnyomás vagy tap. A web-vitals.js v5 az interakciók P98 leghosszabbját veszi INP értéknek, tehát legalább 5-6 interakciót érdemes végrehajtani, hogy stabil értéket kapj.
test('INP a keresőn 200 ms alatt', async ({ page }) => {
const metrics = await measureCWV(page, 'https://example.com/search');
const searchBox = page.locator('input[name="q"]');
await searchBox.click();
// Több interakció szükséges a P98 kalkulációhoz
for (const query of ['ap', 'app', 'appl', 'apple', 'apples']) {
await searchBox.fill(query);
await page.waitForTimeout(120);
}
await page.evaluate(() => document.dispatchEvent(
new Event('visibilitychange')
));
await page.waitForTimeout(300);
const inp = await page.evaluate(() => (window as any).__cwv.INP);
console.log('INP:', inp);
expect(inp).toBeLessThan(200);
});
Egy gyakori hibám az volt kezdetben, hogy egyetlen kattintással próbáltam INP-t mérni, és mindig NaN vagy nagyon zajos érték jött ki. Az INP legalább egyetlen befejezett interakciót igényel (kattintás, billentyű vagy pointerdown/pointerup pár). Egyetlen page.click() hívás technikailag elég, de a P98 statisztikailag zajos lesz egyetlen mintából.
Playwright vagy Lighthouse CI: melyik jobb teljesítményteszthez?
Mindkét eszköz jó, de eltérő célra. A Lighthouse CI a "audit-jellegű" checklist-alapú vizsgálatokban erős: SEO score, accessibility, best practices, PWA. A Playwright a metrikaközpontú regressziós tesztelésben jobb: gyors, testreszabható, valódi interakciókat tud.
Szempont
Playwright 1.50+
Lighthouse CI 12+
Egy oldal mérési ideje
8-15 másodperc
45-90 másodperc
INP mérés valódi interakcióval
Igen, page.click()
Korlátozott, csak szimulált
Testreszabhatóság
Teljes JS-hozzáférés
Config JSON, plugin API
Accessibility / SEO audit
Csak külön plugin-nal
Beépített
Tanulási görbe
Meredek, ha nincs Playwright tapasztalat
Alacsony, CLI-first
Variancia egy futásra
10-15%
15-25%
CI matrix skálázhatóság
Kiváló (workerek)
Nehézkes 10+ URL fölött
Riportformátumok
JSON, HTML, JUnit
JSON, HTML, GitHub Comment
Az én ajánlásom 2026-ra: használd mindkettőt, de más gyakorisággal. Playwrightot minden PR-en futtasd (gyors, olcsó); Lighthouse CI-t hetente egyszer teljes audithoz. Ez a hibrid megközelítés adja a legjobb signal-to-noise arányt.
Beállítás CI-ben: GitHub Actions példa
Az alábbi workflow párhuzamosan futtat három mérést ugyanarra az URL-re, és a mediánt küldi tovább egy összesítő scriptnek. Ez a "3× median" pattern jelentősen csökkenti a hamis pozitív buildbukásokat.
Az összesítő script logikája egyszerű: minden metrikára veszi a 3 futás mediánját, összehasonlítja a perf-budget.json-ban tárolt küszöbökkel, és 1-es exit code-dal kilép, ha bármelyik metrika átlépi a limitet. A regressziós költségvetés fájlt commiteld a repóba, hogy a változásai is code review-n menjenek át.
Regressziós költségvetések és p75 küszöbök
A Largest Contentful Paint, INP és CLS Google-féle "jó" küszöbei a p75-alapú értékek: LCP < 2500 ms, INP < 200 ms, CLS < 0.1. Ezeket használd a CI-ben abszolút küszöbként, ne pedig relatív delta alapján. A relatív delta ("15%-nál rosszabb, mint az előző build") gyakran zajos, mert a szintetikus mérés varianciája elfedi a valódi regressziót. A pontos p75 határértékeket a web.dev Core Web Vitals dokumentációja tartalmazza.
Miért engedékenyebb a /search route küszöbe? Mert a keresőoldal dinamikus, interaktív, és a valós felhasználók is elfogadóbbak a lassulás iránt, ha egyértelműen munkát végez az oldal. A budget értékeket a CrUX-ból származó p75 adatok alapján kalibráld route-onként. Ne találomra vedd őket a levegőből.
Gyakori hibák és megoldások
Öt év perf-mérés után az alábbi öt hiba az, amit szinte minden csapatnál látok. A sorrend nem véletlen: a legelső egyben a leggyakoribb is.
1. Egyetlen futás, nem medián
Egy szintetikus futás varianciája 15-25%. Ha egyetlen mérés dönt a build sikeréről, a fejlesztők 3-4 hét múlva kikapcsolják a perf tesztet, mert "random buktatja a PR-eket". Legalább 3 futás mediánját használd.
2. A cache pollution
A második teszt gyakran gyorsabb, mert a Chromium in-memory cache-e még él. Playwrightban a context.clearCookies() és context.clearPermissions() nem törli a HTTP cache-t. Használj minden teszt előtt új browser.newContext()-et, vagy CDP-n keresztül: client.send('Network.clearBrowserCache').
3. Auth bypass hiánya
Ha az oldal login mögött van, a Playwright a login page-t méri, nem a valódi oldalt. Használj storageState-et (Playwright natívan támogatja), amit egy setup teszt tölt fel, és a perf tesztek onnan olvasnak.
4. Third-party szkriptek varianciája
A Google Analytics, hotjar, chat widgetek nem determinisztikusak, hol 200 ms-ig futnak, hol 1500 ms-ig. Blokkold őket a mérés idejére page.route()-tal, vagy futtass két külön mérési csomagot: "with 3rd party" és "without". A regressziót az utóbbin nézd.
5. Fejlesztői build a production helyett
Dev buildben React devtools, source map, unminified JS: mind lassít. A CI-nek mindig npm run build && npm run start-tal indított production build ellen kell futnia. Ha a Vite HMR-t méred, semmi valós dolgot nem mérsz.
Gyakran ismételt kérdések
Ki tudja váltani a Playwright a Real User Monitoringot?
Nem. A Playwright szintetikus mérést végez egy előre definiált környezetben, míg a RUM valós felhasználók valós eszközein és hálózatán rögzít adatokat. A kettő egymást egészíti ki: a Playwright PR-időben elkapja a regressziókat, a RUM pedig kimutatja, hogy a valós p75 hogyan alakul földrajzi és eszközkategóriák szerint.
Mi a különbség a szintetikus és a valós felhasználói mérés között?
A szintetikus mérés (Playwright, Lighthouse CI) egy kontrollált laboratóriumi környezetben szimulál egy felhasználót: throttled hálózat, tiszta cache, előre meghatározott user flow. A valós felhasználói mérés (RUM, web-vitals.js) a valódi látogatók böngészőjében fut, változó hálózaton és eszközökön. A szintetikus adatok gyorsabbak és stabilabbak; a RUM adatok reprezentatívabbak, de nagyobb varianciájúak.
Miért kapok NaN értéket a Playwright web-vitals mérésnél?
A leggyakoribb ok, hogy a metrikát a lap bezárása vagy háttérbe kerülése előtt olvasod ki. A web-vitals.js a végleges CLS és INP értéket csak a visibilitychange eseményre flushöli. Küldj el egy manuális eseményt (document.dispatchEvent(new Event('visibilitychange'))), várj 300-500 ms-ot, aztán olvasd ki az értéket.
Mennyibe kerül a Playwright perf teszteket futtatni GitHub Actions-ben?
Egy 3× matrix futtatás átlagos oldalra 3-5 GitHub Actions percet fogyaszt. Nyilvános repóknál ingyenes; privát repókban a Team csomag havi 3000 percet ad, ami körülbelül 600-1000 PR mérésére elég. Ha ennél több kell, érdemes self-hosted runner-t húzni, ami stabilabb mérést is ad, mert a hardver konzisztens.
Használhatom a Playwright-et Firefox vagy Safari teljesítménymérésre?
Csak korlátozottan. A web-vitals.js Chromium-specifikus API-kra épül (LargestContentfulPaint API, Event Timing API), amelyek Firefoxban részben, Safariban pedig alig támogatottak 2026-ban. Cross-browser perf-teszthez WebPageTest vagy SpeedCurve a megfelelő eszköz. A Playwrightot Chromium/Chrome mérésre használd.
Daniel started in performance work on the SRE side. He spent six years at Spotify on the Web Player team, where he owned the TTI regression budget for the desktop web app and built the internal dashboard that flagged perf regressions per PR before merge. He left in 2023 to join a small consultancy doing performance audits for fintech and travel companies, mostly in the UK and Nigeria.
His subspecialty is server-side rendering tradeoffs: when streaming SSR actually helps, when it makes things worse on flaky 4G, and the real numbers behind React Server Components for content-heavy sites. He's a heavy Playwright user for perf testing, mistrusts most npm dependencies on principle, and is currently writing a small Rust tool to diff WebPageTest waterfalls across deploys. Outside of work he coaches a junior dev meetup in Manchester.
A Cumulative Layout Shift (CLS) csökkentésének gyakorlati útmutatója 2026-ra: aspect-ratio, font-display: optional, content-visibility és RUM mérés web-vitals.js v4-gyel. Valós kódpéldák képekhez, fontokhoz és SSR streaminghez.
Gyakorlati LCP útmutató 2026-ra: a TTFB, a render-blokkoló erőforrások, a fetchpriority és az AVIF képoptimalizálás, valamint a Soft Navigation LCP mérése SPA-kban. Élesben tesztelt példák és kódrészletek.