Web Performance & Core Web Vitals concept page. Google CWV (LCP < 2.5s, INP < 200ms which replaced FID in 2024, CLS < 0.1). Topology: User device (browser, main thread, web worker) + Edge/CDN + Origin (SSR/API/DB) + Telemetry (RUM beacon, CrUX, Lighthouse CI). Six animated scenarios: Bad LCP (4.2s render-blocking + 800KB hero JPEG), Optimized LCP (1.6s with preload + AVIF + critical CSS + Early Hints), CLS spike (0.4 from img without dimensions + font swap + cookie banner), Bad INP (380ms long task), Good INP (90ms via useTransition + virtualization + Web Worker offload), CI perf budget gate blocking PR. Three ADRs on browser node: performance budget enforcement in CI as hard gate, INP optimization decision tree (useTransition vs scheduler.postTask vs Web Worker), CLS bulletproofing with explicit dimensions + font metric matching.
Web performance - это не косметическая оптимизация после релиза. Для публичного веба она влияет на ranking, conversion, retention и стоимость привлечения. Core Web Vitals стали ranking signal Google с 2021 года, а INP заменил FID в марте 2024. Это значит, что медленная посадочная страница, дергающийся layout или тяжелый click handler могут стать не просто UX-проблемой, а бизнес-регрессией.
Core Web Vitals полезны тем, что привязаны к пользовательскому опыту, а не к абстрактному "Lighthouse score". LCP отвечает на вопрос "когда пользователь увидел главный контент?". INP - "как быстро страница реагирует на худшее взаимодействие в сессии?". CLS - "насколько стабилен layout?". Все три оцениваются на 75-м процентиле реальных пользователей, а не только на ноутбуке разработчика.
Урок нужен, чтобы performance перестал быть набором советов вроде "сжать картинки". Диаграмма показывает pipeline: browser, main thread, worker, CDN/edge, origin, RUM, CrUX и Lighthouse CI. Оптимизация становится архитектурной дисциплиной: budgets, telemetry, ownership, CI gates и ADR по каждому классу проблемы.
Core Web Vitals измеряют три фазы опыта:
Lab data помогает ловить регрессии в PR. Field data показывает реальность: slow 4G, mid-tier CPU, third-party scripts, длинные сессии, scroll-triggered content. Lighthouse - это proxy и CI-инструмент. CrUX/RUM - источник истины для ranking и пользовательского опыта.
В User device находятся browser, main-thread и worker. Это показывает, что performance - не только сеть: main thread может быть заблокирован JS long task, а CPU-heavy работу можно вынести в Web Worker. В Edge / CDN находятся cdn и edge-fn, которые влияют на TTFB, Early Hints, preload и delivery static assets. В Origin находятся ssr, api, db: cache miss и SSR path часто определяют медленный TTFB. В Telemetry находятся rum, rum-store, crux, lhci: field beacons, storage/analytics, Chrome User Experience Report и PR gate.
Edges показывают критический путь: browser -> CDN -> edge/origin -> API -> DB, browser -> main-thread -> worker, browser -> RUM/CrUX, LHCI -> CDN preview. Так видно, что LCP может сломаться на CSS, image priority или origin latency; INP - на main thread; CLS - на layout; а CI и RUM должны ловить разные классы проблем.
bad-lcp показывает 4.2s poor LCP: 200KB render-blocking CSS и 800KB hero JPEG без preload/fetchpriority. Браузер поздно обнаруживает hero image, грузит ее на slow 4G, RUM отправляет LCP=4200 с element=img.hero. Урок: быстрый HTML не спасает, если critical resource поздно найден или слишком тяжелый.
optimized-lcp показывает 1.6s good LCP: Early Hints 103 запускают preload hero.avif до HTML body, CDN дает TTFB 80ms, critical CSS inline, AVIF весит 60KB вместо 800KB JPEG. Урок: LCP чинится не одним трюком, а цепочкой discovery priority + format + cache + CSS.
cls-spike показывает CLS 0.4: font swap, image без dimensions и GDPR banner, вставленный в normal flow. RUM attribution указывает largestShiftTarget=img.photo. Урок: CLS кумулятивен, и несколько маленьких ошибок складываются в poor metric. Фиксы системные: width/height или aspect-ratio, metric-compatible fonts, reserved space, fixed overlay для баннеров.
bad-inp показывает 380ms INP: click handler синхронно фильтрует 10K items и вызывает re-render 10K rows. Main thread заблокирован 350ms, paint задержан. Урок: INP измеряет худшее взаимодействие, поэтому один тяжелый handler может испортить всю сессию.
good-inp показывает 90ms INP: startTransition, virtualization и Web Worker для heavy compute. Пользователь видит pressed state за 60ms, React time-slices reconciliation, список рендерит 20 видимых rows, а pure compute уходит в worker. Урок: нужно выбирать инструмент по природе bottleneck: React reconciliation, background task или CPU-heavy compute.
ci-budget показывает Lighthouse CI gate. PR добавляет rich-text editor на landing, metrics становятся LCP=2.8s и JS=240KB gz, budget fail блокирует merge. После dynamic import editor уезжает на /editor, JS падает до 165KB, PR проходит. Урок: dashboard без hard gate редко работает; budget должен ломать PR до production.
ADR-001 выбирает performance budgets как hard CI gate. Это больно: иногда полезная фича не пройдет, разработчик будет спорить с цифрами, а CI станет длиннее. Но альтернатива хуже: регрессия попадает в production, CrUX p75 портится через 2-4 недели, Search Console присылает alert, а виновата уже серия маленьких PR. Бюджеты должны быть per-route: landing strict, admin тяжелее. Override допустим, но только явно: label, approve perf-owner и новый budget commit.
ADR-002 задает дерево решений для INP. useTransition помогает, когда bottleneck - React update и reconciliation. scheduler.postTask или requestIdleCallback подходят для короткой фоновой работы, но не спасают от long task >50ms, потому что все еще main thread. Web Worker нужен для CPU-heavy задач: JSON.parse большого payload, fuzzy search, image processing, crypto, markdown parsing. Цена worker - postMessage overhead, structured clone, отсутствие DOM access и build setup.
ADR-003 задает layered defense для CLS. Width/height или CSS aspect-ratio резервируют место под media. Font metric overrides через next/font/fontaine убирают reflow при swap. Async slots получают min-height или SSR placeholder. Cookie/GDPR banners не вставляются сверху в normal flow, а показываются fixed overlay. Measurement в production важнее, чем одиночный Lighthouse run, потому что реальный CLS может накапливаться позже в session window.
E-commerce страницы используют image CDN, AVIF/WebP, preload hero, SSR/ISR и strict budgets, потому что LCP напрямую влияет на conversion. News и media сайты борются с CLS из-за ads, embeds, cookie banners и font swaps. SaaS dashboards чаще страдают INP: большие таблицы, фильтры, command palette, rich editors, charts и heavy JSON. Vercel Speed Insights, Sentry Performance, Datadog RUM и custom web-vitals.js beacons собирают field data. Lighthouse CI, WebPageTest и Chrome DevTools используются для lab diagnosis. Cloudflare/Fastly/Vercel edge используют Early Hints, Brotli, cache headers и image optimization, чтобы сокращать critical path.
useTransition вокруг fetch: fetch уже async; проблема обычно в render или compute.Не используйте Core Web Vitals как единственную систему оценки для internal admin tools, где SEO не важен, а пользователи работают на контролируемых устройствах. Там INP и TBT все равно полезны, но LCP/CrUX ranking могут быть вторичны. Не делайте premature optimization без measurement: сначала RUM, attribution, DevTools trace, bundle analyzer. Не выносите все в Web Worker: для задач меньше 20ms overhead может быть дороже выгоды. Не добавляйте SSR/edge только ради LCP, если главный bottleneck - 800KB hero или 300KB JS. Не гонитесь за CLS=0 любой ценой через пустые placeholders, которые ухудшают perceived UX; резервируйте место честно и предсказуемо.
Внешние ориентиры: web.dev Core Web Vitals docs, Chrome Developers materials по INP, web-vitals attribution API, Lighthouse CI docs, WebPageTest, High Performance Browser Networking by Ilya Grigorik, Addy Osmani materials по image/font performance и React docs по useTransition.