Skip to content
25 / 36

Что такое Navigation Timing API?


Полный ответ

Каждая загрузка страницы создаёт одну запись типа PerformanceNavigationTiming:

JavaScript
const [nav] = performance.getEntriesByType('navigation');

// Полная хронология загрузки (в миллисекундах от начала навигации)
console.log({

    // Этап 1: Подготовка
    redirectTime:    nav.redirectEnd - nav.redirectStart,
    workerTime:      nav.workerStart > 0 ? nav.fetchStart - nav.workerStart : 0,

    // Этап 2: Сетевое подключение
    dnsLookup:       nav.domainLookupEnd - nav.domainLookupStart,
    tcpConnect:      nav.connectEnd - nav.connectStart,
    tlsHandshake:    nav.secureConnectionStart > 0
    ? nav.connectEnd - nav.secureConnectionStart
    : 0,

    // Этап 3: Запрос-ответ
    requestTime:     nav.responseStart - nav.requestStart,   // TTFB (серверная часть)
    responseTime:    nav.responseEnd - nav.responseStart,     // скачивание тела ответа

    // Этап 4: Обработка документа
    domParsing:      nav.domInteractive - nav.responseEnd,
    domContentLoaded: nav.domContentLoadedEventEnd - nav.domContentLoadedEventStart,
    domComplete:     nav.domComplete - nav.domInteractive,

    // Этап 5: Событие load
    loadEvent:       nav.loadEventEnd - nav.loadEventStart,

    // Общее время
    totalTime:       nav.loadEventEnd - nav.startTime,
  });

Визуальная схема тайминга:

JavaScript
startTime
|
|-- redirectStart / redirectEnd         (редиректы)
|-- workerStart                         (Service Worker)
|-- fetchStart                          (начало fetch)
|-- domainLookupStart / End             (DNS)
|-- connectStart / secureConnectionStart / connectEnd  (TCP + TLS)
|-- requestStart                        (отправка запроса)
|-- responseStart                       (первый байт = TTFB)
|-- responseEnd                         (весь ответ получен)
|-- domInteractive                      (DOM распарсен)
|-- domContentLoadedEventStart / End    (DOMContentLoaded)
|-- domComplete                         (все ресурсы загружены)
|-- loadEventStart / loadEventEnd       (window.onload)

Дополнительные свойства:

JavaScript
const [nav] = performance.getEntriesByType('navigation');

// Тип навигации
console.log(nav.type);
// 'navigate'       -- обычный переход
// 'reload'         -- перезагрузка
// 'back_forward'   -- кнопки назад/вперёд
// 'prerender'      -- предрендеренная страница

// Размер документа
console.log({
    transferSize:    nav.transferSize,    // сжатый размер (по сети)
    encodedBodySize: nav.encodedBodySize, // размер тела (сжатый)
    decodedBodySize: nav.decodedBodySize, // размер тела (распакованный)
  });

// Протокол
console.log(nav.nextHopProtocol); // "h2", "h3", "http/1.1"

📌 Реальные кейсы

Дашборд производительности:

JavaScript
function getNavigationMetrics() {
  const [nav] = performance.getEntriesByType('navigation');
  if (!nav) return null;

  return {

    // Сетевые метрики
    dns: Math.round(nav.domainLookupEnd - nav.domainLookupStart),
    tcp: Math.round(nav.connectEnd - nav.connectStart),
    ttfb: Math.round(nav.responseStart - nav.requestStart),
    download: Math.round(nav.responseEnd - nav.responseStart),

    // DOM-метрики
    domParse: Math.round(nav.domInteractive - nav.responseEnd),
    domReady: Math.round(nav.domContentLoadedEventEnd - nav.startTime),
    windowLoad: Math.round(nav.loadEventEnd - nav.startTime),

    // Мета
    protocol: nav.nextHopProtocol,
    type: nav.type,
    compressed: nav.transferSize < nav.decodedBodySize,
    compressionRatio: nav.decodedBodySize > 0
    ? (1 - nav.transferSize / nav.decodedBodySize).toFixed(2)
    : 'N/A',
  };
}

// Отправка после полной загрузки
window.addEventListener('load', () => {
    setTimeout(() => {
        const metrics = getNavigationMetrics();
        if (metrics) {
          navigator.sendBeacon('/api/perf', JSON.stringify(metrics));
        }
      }, 0);
  });

Сравнение Navigation Timing Level 1 и Level 2:

JavaScript
// ❌ Level 1 (устаревший) -- через performance.timing
const ttfb = performance.timing.responseStart - performance.timing.requestStart;

// ✅ Level 2 (текущий) -- через PerformanceNavigationTiming
const [nav] = performance.getEntriesByType('navigation');
const ttfb = nav.responseStart - nav.requestStart;

// Level 2 преимущества:
// -- Возвращает PerformanceEntry (совместим с PerformanceObserver)
// -- Точнее (high-resolution time)
// -- Содержит serverTiming, transferSize

Резюме

Navigation Timing API раскладывает загрузку страницы на точные этапы: DNS, TCP, TLS, TTFB, парсинг DOM, загрузка ресурсов. Используй Level 2 (getEntriesByType('navigation')) вместо устаревшего performance.timing. Это основной инструмент для диагностики медленных загрузок и мониторинга в production.

Что такое Navigation Timing API? | JScriptiser