Монитор Web Vitals во вкладке — LCP / CLS / INP в Output Console без DevTools
Web Vitals (LCP, CLS, INP) — это 3 метрики, которые Google использует как фактор SEO-ранжирования. Стандартный способ их измерения: Lighthouse в DevTools — 30 секунд на аудит, ручной запуск. Альтернатива: API PerformanceObserver, встроенный в браузеры. Плюс JS-правило JustZix = пассивный монитор, который рапортует в Output Console для каждой посещённой страницы. Идеально для быстрой проверки своих проектов или анализа конкурентов.
JS-правило — полный перехват Web Vitals
Scope: *://*/* или по доменам, если хочешь мониторить только свои сайты.
// JS-правило «Монитор Web Vitals»
const vitals = { LCP: null, CLS: 0, FCP: null, TTFB: null, INP: null };
// === LCP (Largest Contentful Paint) ===
new PerformanceObserver((list) => {
const entries = list.getEntries();
const last = entries[entries.length - 1];
vitals.LCP = Math.round(last.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
// === CLS (Cumulative Layout Shift) ===
let clsEntries = [];
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsEntries.push(entry);
vitals.CLS = clsEntries.reduce((s, e) => s + e.value, 0);
}
}
}).observe({ type: 'layout-shift', buffered: true });
// === FCP (First Contentful Paint) ===
new PerformanceObserver((list) => {
const fcp = list.getEntries().find(e => e.name === 'first-contentful-paint');
if (fcp) vitals.FCP = Math.round(fcp.startTime);
}).observe({ type: 'paint', buffered: true });
// === TTFB (Time to First Byte) ===
const nav = performance.getEntriesByType('navigation')[0];
if (nav) vitals.TTFB = Math.round(nav.responseStart - nav.requestStart);
// === INP (Interaction to Next Paint) ===
let worstINP = 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > worstINP) {
worstINP = Math.round(entry.duration);
vitals.INP = worstINP;
}
}
}).observe({ type: 'event', buffered: true, durationThreshold: 16 });
// Отчёт через 5 секунд после загрузки + при unload (финальные значения)
const report = () => {
const status = (val, good, poor) =>
val === null ? '?' : val <= good ? '✓' : val <= poor ? '⚠' : '✗';
JUSTZIX.log('=== Web Vitals ===');
JUSTZIX.log(`LCP: ${vitals.LCP ?? '?'}ms ${status(vitals.LCP, 2500, 4000)} (цель <2.5s)`);
JUSTZIX.log(`CLS: ${vitals.CLS.toFixed(3)} ${status(vitals.CLS, 0.1, 0.25)} (цель <0.1)`);
JUSTZIX.log(`FCP: ${vitals.FCP ?? '?'}ms ${status(vitals.FCP, 1800, 3000)} (цель <1.8s)`);
JUSTZIX.log(`TTFB: ${vitals.TTFB ?? '?'}ms ${status(vitals.TTFB, 800, 1800)} (цель <800ms)`);
JUSTZIX.log(`INP: ${vitals.INP ?? '?'}ms ${status(vitals.INP, 200, 500)} (цель <200ms)`);
};
setTimeout(report, 5000);
window.addEventListener('beforeunload', report);
JUSTZIX.info(`[Vitals] Монитор активен для ${location.hostname}`);
Что ты видишь в Output Console
Через 5 секунд после загрузки:
[INFO] [Vitals] Монитор активен для www.justzix.com
[LOG] === Web Vitals ===
[LOG] LCP: 1240ms ✓ (цель <2.5s)
[LOG] CLS: 0.024 ✓ (цель <0.1)
[LOG] FCP: 680ms ✓ (цель <1.8s)
[LOG] TTFB: 145ms ✓ (цель <800ms)
[LOG] INP: 85ms ✓ (цель <200ms)
Каждая метрика с визуальным статусом:
- ✓ = в хорошем интервале («Good» у Google)
- ⚠ = в интервале «Needs improvement»
- ✗ = в интервале «Poor»
Сценарий 1 — аудит своего сайта без Lighthouse
Классика: деплой на staging, открой вкладку, проверь, зелёные ли Web Vitals. С Lighthouse: 30 с ожидания. С JustZix: 5 с, и рапортует для каждой следующей посещённой страницы в этой сессии.
Сценарий 2 — сравнение с конкурентами
Посети конкурента. Output Console показывает его LCP/CLS/INP. Твой сайт — сравнение 1:1, те же сетевые условия, то же устройство.
Сценарий 3 — живой монитор во время разработки
Защёлкни pane Output Console на правую сторону. Запусти свой dev-сервер localhost. Каждый F5 → JUSTZIX.log со свежими vitals. Видишь вживую эффект своих изменений (например, lazy-load изображения → LCP вверх, layout shift → CLS вверх).
Сценарий 4 — экспорт JSON действием КНОПКА
// Действие КНОПКА «📊 Экспорт vitals»
const data = {
url: location.href,
timestamp: new Date().toISOString(),
vitals: window.JZ_LATEST_VITALS || {}
};
const json = JSON.stringify(data, null, 2);
navigator.clipboard.writeText(json);
JUSTZIX.log('Vitals экспортированы в буфер обмена.');
В JS-правило добавь строку: window.JZ_LATEST_VITALS = vitals; после каждого обновления. У КНОПКИ теперь есть текущий снапшот для экспорта в документацию / Slack.
Ловушки
- LCP в single-page приложениях. Смены маршрута SPA не запускают новое измерение LCP. Обходной путь: слушай события popstate и сбрасывай observer'ы.
- CLS продолжается после загрузки. Страницы с lazy-load изображениями могут увеличивать CLS часами. Финальный CLS = значение при unload (beforeunload). Lighthouse прекращает измерение через 3-5 с.
- INP требует реального взаимодействия. Статическая страница без кликов → INP = null. Открой страницу + прокрути/кликни перед чтением метрик.
- TTFB = responseStart - requestStart, БЕЗ DNS/соединения. Полный TTFB это
responseStart - fetchStart. Реализации варьируются. - PerformanceObserver buffered: true — перехватывает события, случившиеся до инициализации observer'а. Без этого pre-init записи теряются.
Что делать дальше
- Output Console подробно — куда попадает JUSTZIX.log
- Отладка GTM без разработчиков — родственный паттерн мониторинга
- window.JZ + JUSTZIX — программный API
Установи JustZix — монитор Web Vitals с нулевой конфигурацией, который ЗАМЕЧАЕТ проблему раньше пользователя.
Оцени эту статью
Оценок пока нет — оцени первым.