awesome-everything EN
↑ Обратно к восхождению

Производительность

V8 JIT-пайплайн, HTTP-приоритеты и безопасность bundle

Суть Четыре уровня компиляции V8, HTTP/3 Extensible Priorities (RFC 9218), 103 Early Hints и Subresource Integrity — senior-уровень bundle delivery: механизмы, объясняющие, почему меньший bundle всё равно варьируется в 2-3x в зависимости от способа доставки.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 18 min

Два приложения с одинаковым homepage bundle 100 КБ. У одного LCP 1,4 с; у другого 2,3 с. Размеры bundle’ов идентичны. Разница — в способе доставки bundle: resource priorities, Early Hints и достигают ли критичные функции оптимизированных тиров V8 до interactive страницы.

Многоуровневый пайплайн компиляции V8

V8 компилирует JavaScript через четыре прогрессивных уровня, меняя compile-стоимость на скорость выполнения.

Ignition — bytecode-интерпретатор. Каждая функция начинает здесь. Compile-стоимость минимальна; выполнение в ~5-10 раз медленнее оптимизированного native кода. Код, запускающийся только раз (module-level инициализация), обычно остаётся в Ignition.

Sparkplug (Chrome 91, 2021) — неоптимизирующий baseline JIT. Компилирует bytecode в machine code без inlining или type speculation. Compile-стоимость похожа на Ignition; выполнение в ~5x быстрее. Функции автоматически повышаются до Sparkplug после примерно 100 запусков.

Maglev (Chrome 117, 2023) — mid-tier оптимизирующий JIT с некоторым inlining и type speculation. Повышается после большего числа итераций.

TurboFan — топ-tier оптимизирующий компилятор. Полный inlining, escape analysis, type speculation, loop unrolling. Compile-стоимость высока (10-100 мс per hot функция), но выполнение приближается к native speed. Функции достигают TurboFan только после доказанного hot статуса.

Implications для bundle budgets: total parse-стоимость пропорциональна байтам bundle — каждый байт парсится один раз независимо от уровня. Initial compile-стоимость пропорциональна коду, реально запускаемому при старте. Код, никогда не запускающийся, парсится но никогда не компилируется (lazy compilation V8). Размер bundle важнее всего для parse и initial compile; скорость выполнения hot функций зависит больше от формы кода (type stability, allocation patterns), чем от размера bundle.

Ловушки деоптимизации: V8 спекулятивно оптимизирует функции на основе наблюдаемых типов. Если функция, скомпилированная с предположением, что аргумент всегда number, получает string, V8 деоптимизирует её — выбрасывает TurboFan-версию и откатывается к Sparkplug или Ignition. Deopt-цикл — функция, которая оптимизируется, деоптимизируется и повторно оптимизируется — может жечь CPU даже при маленьком bundle. Диагноз через Chrome DevTools Performance tab; ищи события «Deoptimize».

HTTP/3 Extensible Priorities (RFC 9218)

HTTP/1.1 и HTTP/2 не имеют надёжной client-to-server сигнализации приоритетов. HTTP/3 (over QUIC) реализует RFC 9218: браузеры шлют заголовок Priority с каждым запросом. Серверы и CDN, реализующие его, отдают критичные ресурсы первыми, даже если они были запрошены последними.

Priority: u=1          # Высокая срочность (0=наибольшая, 7=наименьшая)
Priority: u=3, i       # Средняя срочность, инкрементальная доставка

Браузеры автоматически назначают приоритеты: CSS в <head> получает urgency 0; lazy-loaded images — urgency 5-6. Маленький критичный bundle, конкурирующий с большим deferred vendor chunk за bandwidth, отдаётся первым при правильной поддержке CDN.

Риск мисконфигурации: неверно настроенный HTTP/3 priority может стереть 20-30% преимуществ code-splitting, если CDN шлёт большой deferred chunk первым несмотря на browser priority hints. Проверь в Chrome Network panel под колонкой «Priority».

103 Early Hints (RFC 8297)

Сервер, знающий, что собирается отдать index.html, также знает критичные ресурсы, которые нужны этой странице — критичный JS chunk, основной шрифт, hero image. С 103 Early Hints сервер шлёт информационный 103 ответ с заголовками Link: ...; rel=preload до завершения генерации HTML. Браузер начинает загружать критичные ресурсы пока сервер ещё строит ответ.

HTTP/2 103 Early Hints
Link: </static/app.abc123.js>; rel=preload; as=script
Link: </fonts/inter.woff2>; rel=preload; as=font; crossorigin

Типичный выигрыш: 100-500 мс в доставке критичных ресурсов, в зависимости от времени генерации HTML на сервере и network latency. Cloudflare, Fastly и Vercel поддерживают 103. Большинство production-команд пока не используют Early Hints; это senior-уровень оптимизация, проявляющаяся в 95th-percentile LCP улучшениях.

ТехникаМеханизмТипичный выигрыш
HTTP/3 RFC 9218 prioritiesКритичный chunk отдаётся до deferredПредотвращает потерю 20-30% split-преимущества
103 Early HintsPreload заголовки до готовности HTML100-500 мс LCP улучшение
modulepreloadDownload + parse-compile ESM модуль заблаговременноУбирает parse-стоимость с critical path

Subresource Integrity и CSP

Subresource Integrity (SRI): атрибут integrity на тегах <script> и <link> включает hash ожидаемого содержимого файла. Если CDN или third-party хост скомпрометирован и отдаёт изменённый скрипт, браузер вычисляет hash и отклоняет файл.

<script src="https://cdn.example.com/lib.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Без SRI компромисс CDN тихо шлёт вредоносный JS всем пользователям. С SRI браузер отказывается от скрипта. Production-grade: SRI на все third-party script теги; build tooling автоматически генерирует SRI hashes для first-party ассетов.

CSP + bundle delivery: script-src 'self' https://cdn.example.com ограничивает origins, от которых могут грузиться скрипты. Частая мисконфигурация: 'unsafe-inline' разрешает inline scripts, сводя на нет защиту от XSS-injected скриптов. Используй nonces или hashes для намеренных inline scripts.

Production observability: bundle size как RUM метрика

Помимо LCP/INP/CLS, senior-команды трекают gzip’d bundle size per route как custom RUM метрику. При деградации LCP первая корреляция для проверки — изменился ли размер bundle в том же деплое. Некоторые платформы (Vercel Analytics, Sentry Performance) предоставляют это автоматически; другие требуют custom beacon.

Паттерны production-отказов: Pinterest 2017 (один большой bundle → 12 с блокировки main thread, переписан на chunks → bounce -40%); Tinder 2019 (admin panel на consumer routes → 200 КБ удалено → конверсия +5%); Stripe 2020 (Stripe.js 80 КБ на каждом checkout → маленький loader + lazy → TTI -35%). Паттерн всегда структурный: split, lazy, replace — не compress-more.

Почему это работает

Почему deopt-цикл важен для bundle budgets? Деоптимизация происходит когда V8 обнаруживает, что его type assumptions были неверны и откатывается к более медленным уровням. Если deopt в часто вызываемой функции (например, render loop), CPU overhead мультипликативный — функция повторно JIT-компилируется. Bundle 50 КБ с deopt-циклом в hot функции может казаться медленнее bundle 200 КБ без него. Bundle analysis и —trace-deopt — разные диагностические оси; senior performance работа использует обе.

Викторина

Команда профилирует V8 и находит: render-функция деоптимизируется 50 раз в секунду. Bundle — 90 КБ. Что исправить, и помогает ли уменьшение bundle?

Викторина

Команда включает code splitting, но их CDN неверно настроен с равными HTTP/3 приоритетами для всех chunks. Какой вероятный performance impact?

Викторина

Script tag без атрибута integrity грузит скрипт с third-party CDN. CDN скомпрометирован и отдаёт изменённый скрипт. Что происходит без SRI и с ним?

Вспомните перед уходом
  1. 01
    Опиши четыре уровня компиляции V8 и что каждый даёт.
  2. 02
    Что определяет RFC 9218 и почему это важно для code-split bundles?
  3. 03
    PR вводит функцию, обрабатывающую и strings и numbers. После деплоя RUM показывает INP регрессию на конкретном route. Вероятный диагноз и fix?
Итог

Размер bundle задаёт parse-стоимость, но ceiling определяется способом доставки и компиляции bundle. Четыре JIT-уровня V8 прогрессивно компилируют hot функции от Ignition до TurboFan — байты bundle влияют на parse, но type-нестабильные hot функции вызывают deopt-циклы, доминирующие execution-временем независимо от размера. HTTP/3 RFC 9218 priorities обеспечивают правильный порядок прихода code-split чанков; неверно настроенный CDN стирает до 30% преимуществ split. 103 Early Hints даёт браузеру 100-500 мс фору на критичные ресурсы до прихода HTML. Subresource Integrity и CSP защищают доставку от компрометации CDN. Вместе они формируют senior performance-слой: разницу между теоретически корректным bundle budget и тем, который реально доставляет performance, обещанный измерениями.

Связанные уроки
встречается в260
Продолжить восхождение ↑Bundle budgets: тест с множественным выбором
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.