Performance API

Performance API позволяет собирать детальные данные о времени загрузки страниц, событиях рендеринга, сетевых запросах и других метриках производительности веб-приложений. Puppeteer, как инструмент для автоматизации Chromium, предоставляет удобный доступ к этому API через контекст страницы, что делает его незаменимым для тестирования и анализа производительности.

Подключение и базовая настройка

Для начала работы необходимо импортировать Puppeteer и создать экземпляр браузера и страницы:

const puppeteer = require(&

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
})();

Важно: параметр waitUntil: ‘networkidle2’ гарантирует, что страница полностью загрузилась, и большинство сетевых запросов завершены. Это критично для корректного измерения производительности.

Доступ к Performance API

Performance API доступен через объект window.performance на странице. Для получения данных из Puppeteer используется метод page.evaluate, который позволяет выполнять код в контексте браузера:

const performanceTiming = await page.evaluate(() => JSON.stringify(window.performance.timing));
console.log(JSON.parse(performanceTiming));

Ключевые моменты объекта performance.timing:

  • navigationStart — момент начала навигации.
  • responseStart — время первого байта ответа сервера.
  • domContentLoadedEventEnd — завершение события DOMContentLoaded.
  • loadEventEnd — завершение загрузки страницы.

На основе этих значений можно вычислять метрики, например:

const metrics = await page.evaluate(() => {
  const t = window.performance.timing;
  return {
    backendTime: t.responseStart - t.navigationStart,
    frontendTime: t.loadEventEnd - t.responseStart,
    totalTime: t.loadEventEnd - t.navigationStart
  };
});
console.log(metrics);

Использование Navigation Timing Level 2

Современные браузеры поддерживают Navigation Timing Level 2, который предоставляет более точные метрики и улучшенную совместимость с асинхронными сценариями:

const navEntries = await page.evaluate(() => {
  return performance.getEntriesByType('navigation')[0].toJSON();
});
console.log(navEntries);

Полезные поля:

  • domInteractive — время, когда DOM готов к взаимодействию.
  • domComplete — когда DOM полностью построен.
  • transferSize — общий размер переданных данных.
  • decodedBodySize — размер тела ответа после декодирования.

Эти данные особенно важны для анализа узких мест в рендеринге и сетевых задержках.

PerformanceObserver для мониторинга событий

Puppeteer позволяет использовать PerformanceObserver для отслеживания различных событий производительности в реальном времени:

await page.evaluate(() => {
  const observer = new PerformanceObserver((list) => {
    list.getEntries().forEach((entry) => console.log(entry));
  });
  observer.observe({ entryTypes: ['resource', 'paint'] });
});

Типы событий:

  • resource — загрузка скриптов, изображений и других ресурсов.
  • paint — метрики отрисовки, включая first-paint и first-contentful-paint.
  • longtask — продолжительные задачи JavaScript, влияющие на отзывчивость страницы.

Использование PerformanceObserver позволяет фиксировать ключевые показатели во время тестирования, а не только после полной загрузки страницы.

Сбор метрик рендеринга

Метрики рендеринга помогают анализировать, как быстро пользователь видит контент:

const paintMetrics = await page.evaluate(() => {
  const [fp, fcp] = performance.getEntriesByType('paint');
  return {
    firstPaint: fp.startTime,
    firstContentfulPaint: fcp.startTime
  };
});
console.log(paintMetrics);

Объяснение:

  • firstPaint — момент, когда браузер впервые отрисовал что-либо на экране.
  • firstContentfulPaint — момент, когда появился первый видимый контент, важный для UX.

Автоматизация замеров в Puppeteer

Для регулярного тестирования можно объединить сбор метрик в функцию:

async function getPerformanceMetrics(url) {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'networkidle2' });

  const metrics = await page.evaluate(() => {
    const t = performance.timing;
    const paints = performance.getEntriesByType('paint');
    return {
      backendTime: t.responseStart - t.navigationStart,
      frontendTime: t.loadEventEnd - t.responseStart,
      totalTime: t.loadEventEnd - t.navigationStart,
      firstPaint: paints.find(p => p.name === 'first-paint')?.startTime || 0,
      firstContentfulPaint: paints.find(p => p.name === 'first-contentful-paint')?.startTime || 0
    };
  });

  await browser.close();
  return metrics;
}

Эта функция позволяет многократно измерять производительность разных страниц и строить на основе данных аналитические отчёты.

Интеграция с CI/CD

Performance API в Puppeteer можно интегрировать в CI/CD пайплайны для автоматического контроля метрик на каждой сборке. Например:

  • Сравнение firstContentfulPaint с пороговым значением.
  • Выявление медленных ресурсов с помощью PerformanceObserver.
  • Автоматическая запись JSON-отчётов для последующего анализа.

Практические рекомендации

  1. Использовать waitUntil: ‘networkidle2’ или networkidle0 для корректного измерения полной загрузки.
  2. Параллельно собирать performance.timing и paint-метрики для комплексного анализа.
  3. Настраивать Puppeteer с опцией headless: true для стабильных и воспроизводимых замеров.
  4. Сохранять метрики в формате JSON для возможности агрегирования и построения графиков.

Performance API в Puppeteer предоставляет мощный инструмент для глубокого анализа производительности веб-приложений. Он позволяет измерять время загрузки, оценивать эффективность рендеринга и выявлять узкие места, обеспечивая основу для оптимизации скорости и отзывчивости интерфейса.