Playwright teljesítménytesztek 2026: Core Web Vitals mérése CI-ben

Így mérj Core Web Vitals metrikákat Playwrighttel: web-vitals.js integráció, CDP throttling, INP mérés, GitHub Actions és regressziós költségvetések 2026-ban.

Playwright Web Vitals CI 2026
On this page
  1. Miért Playwright a teljesítményteszthez 2026-ban?
  2. Alapkörnyezet: Playwright 1.50 és web-vitals.js v5 telepítése
  3. Hogyan mérjünk Core Web Vitals metrikákat Playwright-tel?
  4. Chrome DevTools Protocol throttling: hálózat és CPU
  5. Hogyan mérjük az INP-t Playwrightban?
  6. Playwright vagy Lighthouse CI: melyik jobb teljesítményteszthez?
  7. Beállítás CI-ben: GitHub Actions példa
  8. Regressziós költségvetések és p75 küszöbök
  9. Gyakori hibák és megoldások

Frissítve: 2026. július 10.

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.

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.

npm init -y
npm install --save-dev @playwright/test@^1.50 web-vitals@^5
npx playwright install chromium --with-deps

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.

test.beforeEach(async ({ page }) => {
  const client = await page.context().newCDPSession(page);

  // "Slow 4G" preset, Lighthouse Mobile baseline
  await client.send('Network.emulateNetworkConditions', {
    offline: false,
    downloadThroughput: (1.6 * 1024 * 1024) / 8, // 1.6 Mbps
    uploadThroughput: (750 * 1024) / 8,           // 750 kbps
    latency: 150,                                  // 150 ms RTT
  });

  // 4x CPU slowdown, kozepes Android telefonhoz kozeli
  await client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
});

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.

SzempontPlaywright 1.50+Lighthouse CI 12+
Egy oldal mérési ideje8-15 másodperc45-90 másodperc
INP mérés valódi interakcióvalIgen, page.click()Korlátozott, csak szimulált
TestreszabhatóságTeljes JS-hozzáférésConfig JSON, plugin API
Accessibility / SEO auditCsak külön plugin-nalBeépített
Tanulási görbeMeredek, ha nincs Playwright tapasztalatAlacsony, CLI-first
Variancia egy futásra10-15%15-25%
CI matrix skálázhatóságKiváló (workerek)Nehézkes 10+ URL fölött
RiportformátumokJSON, HTML, JUnitJSON, 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.

name: Perf Regression

on: pull_request

jobs:
  measure:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        run: [1, 2, 3]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npx playwright install chromium --with-deps
      - run: npx playwright test perf-tests/ --reporter=json > run-${{ matrix.run }}.json
      - uses: actions/upload-artifact@v4
        with:
          name: perf-run-${{ matrix.run }}
          path: run-${{ matrix.run }}.json

  aggregate:
    needs: measure
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
      - run: node scripts/median-and-budget.js perf-run-*

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.

Egy jó perf-budget.json így néz ki:

{
  "budgets": [
    {
      "path": "/",
      "LCP": 2500,
      "INP": 200,
      "CLS": 0.1,
      "TTFB": 800
    },
    {
      "path": "/search",
      "LCP": 3000,
      "INP": 200,
      "CLS": 0.15
    }
  ]
}

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.