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

Браузер и фронтенд-рантайм

Пять канонических поломок: где производство стабильно ломается

Суть Зловещая долина гидратации как объединяющий сбой и пять канонических поломок — поздний hero-элемент (LCP), несоответствие гидратации (CLS), мегаморфный путь отрисовки (INP), устаревший кеш сервис-воркера (корректность), синхронный обработчик (INP) — каждая владеет другим слоем.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 22 min

Команда запускает Lighthouse: 94, зелёный. Затем приходит RUM-отчёт — LCP в поле 6.8 с, INP 540 мс, CLS 0.21, все плохо. Лаборатория тестировала чистую сессию без сервис-воркера; в поле — реальные пользователи на среднебюджетных телефонах, тапающие кнопки во время гидратации. Лаборатория и поле измеряют одну страницу — с разных углов, и угол поля — это то, в чём живут пользователи.

Зловещая долина как объединяющий сбой.

Единственный сбой, связывающий весь браузерный раздел воедино — это зазор между «нарисовано» и «интерактивно» — зловещая долина гидратации. Это не один баг; это структурное свойство серверно-рендеренных, клиентски-гидрируемых приложений. Каждый другой сбой в этом уроке либо расширяет эту долину, либо происходит внутри неё.

Сеньорный фрейм: страница имеет два момента завершения — LCP-ish («выглядит готово») и TTI-ish («работает»), и всё мастерство современной фронтенд-производительности — это сжатие расстояния между ними. Вот пять канонических поломок — места, где производство наиболее стабильно ломается вдоль трассы.

Пять канонических поломок — слой и метрика
Поломка 1: поздний hero-элемент
Слои 2+5 → LCP
Поломка 2: несоответствие гидратации
Слой 6 → CLS + корректность
Поломка 3: мегаморфный путь отрисовки
Слои 4+7 → INP
Поломка 4: устаревший кеш сервис-воркера
Слои 1+8 → корректность
Поломка 5: синхронная работа в обработчике
Слой 7 → INP

Поломка 1 — Поздняя загрузка hero-изображения (LCP).

Hero-изображение — LCP-элемент, но оно указано в CSS как background-image, или несёт loading="lazy", или внедряется JavaScript-ом. Сканер предзагрузки не может его увидеть, поэтому загрузка начинается поздно — и LCP, который измеряет именно этот элемент, приземляется на 4+ секундах. Трасса показывает длинную фазу задержки загрузки ресурса.

Исправление: LCP-изображение должно быть обычным <img> в исходном HTML, загружаться жадно, с fetchpriority="high". Это слой 2 (обнаружение), падающий, и слой 5 (отрисовка), платящий за это.

Поломка 2 — Несоответствие гидратации (CLS плюс корректность).

Компонент рендерит значение, которое различается между сервером и клиентом — временну́ю метку, флаг из localStorage, цену в локальном формате. Серверный HTML и первый рендер клиента расходятся; React выбрасывает серверное поддерево и перерендеривает его, мигая изменившимся контентом и вызывая всплеск CLS. Трасса показывает маркер сдвига макета сразу после задачи гидратации.

Исправление: детерминизм рендеринга — откладывать только-клиентские значения в useEffect после гидратации. Это слой 6 (гидратация), падающий потому что сериализованное состояние не было точно воспроизведено на клиенте.

Поломка 3 — Мегаморфный путь отрисовки (INP).

Обработчик «Добавить в корзину» запускает перерисовку, и горячая функция на этом пути — средство доступа к свойству, компаратор — мегаморфна: она видела слишком много форм объектов, поэтому V8 не может использовать встроенный кеш и откатывается к медленным поискам. Перерисовка, которая должна занять 5 мс, занимает 80 мс, и INP для взаимодействия плохой. Трасса показывает длинную полосу выполнения скриптов внутри взаимодействия.

Исправление: стабилизировать формы объектов, чтобы встроенные кеши V8 оставались мономорфными. Это слои 4 (V8) и 7 (взаимодействие), переплетённые.

Поломка 4 — Устаревший кеш сервис-воркера (корректность).

Деплой привозит новый HTML и новый JS-бандл, но сервис-воркер отдаёт прошлонедельный закешированный app.js в режиме cache-first против HTML этой недели — несоответствие версий модулей, ошибка во время выполнения. Или хуже — сломанная оболочка приложения закешированна, и каждый повторный посетитель застрял на ней, минуя сеть, где живёт исправление.

Исправление: имена ассетов с хешем содержимого, кеши с версионными метками, очищаемые в activate, навигация network-first, рубильник. Это слои 1 / 8 (воркер), падающие через состояние — кеш пережил свою корректность.

Поломка 5 — Синхронная работа в обработчике события (INP).

Обработчик «Добавить в корзину» делает что-то синхронное и тяжёлое в основном потоке перед уступкой — отправляет синхронный аналитический маяк, запускает большой JSON.parse, пересчитывает производный список. Время обработки обработчика само по себе превышает бюджет INP в 200 мс. Трасса показывает длинную жёлтую полосу скриптинга между вводом и следующей отрисовкой.

Исправление: делать минимум для обновления UI, затем уступать (scheduler.yield()), и переносить чистые тяжёлые вычисления в воркер. Это слой 7 (взаимодействие), падающий напрямую из-за правил цикла событий.

Почему каждую поломку сложно диагностировать с одного слоя.

Поломка 1 выглядит как «медленное изображение» для того, кто знает только сеть — но изображение было нормального размера; настоящая причина — обнаружение, проблема слоя парсинга. Поломка 3 выглядит как «React медленный» для того, кто знает только рекурсор — но рекурсор был в порядке; настоящая причина — мегаморфная форма, проблема V8. Весь смысл трассировки от начала до конца в том, что симптом и причина рутинно находятся в разных слоях, и только тот, кто видит всю цепь, перестаёт чинить симптомы.

Найди ошибку
log
[TTFB]  2980 мс  (попадание в сервис-воркер не произошло; холодный источник)
[FCP]   3240 мс
[LCP]   6800 мс  элемент: div.hero[style*=background-image]
[INP]   540 мс   взаимодействие: click .add-to-cart
               скрипт LoAF: vendor.js (гидратация) 482 мс
[CLS]   0.21     источник: #price (несоответствие гидратации)

Одна RUM-сессия, все метрики плохи. Пройди цепь: назови слой за каждым числом и одно наиболее высокоэффективное исправление, с которого начать.

Выбери лучший вариант

Страница товара имеет хороший LCP, но плохой INP в первые несколько секунд. У тебя есть время на одно исправление в этом спринте. Выбери.

Какой RFC?

Какой инструмент показывает работу сети, основного потока и GPU страницы на одной перекрывающейся временно́й шкале — основу метода диагностики по трём трекам?

Спроектируй

Ты наследуешь страницу товара e-commerce из этой трассы. Данные поля: LCP 4.8 с, INP 480 мс, CLS 0.18 — все плохи. Разработай полный план исправления, слой за слоем, в порядке приоритета.

  • Среднебюджетный Android, 4G — реальный сегмент p75 пользователей.
  • Серверно-рендеренный React с уже зарегистрированным сервис-воркером.
  • Hero-изображение, цена, Добавить-в-корзину, отзывы ниже сгиба.
  • Нужно улучшить все три Core Web Vitals до «хорошего» на поле p75.
  • Каждое исправление должно называть целевой слой и метрику, которую оно двигает.
  • Упорядочи работу так, чтобы наиболее высокоэффективные исправления шли первыми.
Викторина

Поломка 1 (поздний hero) выглядит как «медленное изображение», поломка 3 (мегаморфный путь) выглядит как «React медленный». Что это иллюстрирует о трассировке?

Викторина

В RUM-логе TTFB — 2980 мс. Почему исправление TTFB — наиболее высокоэффективная отправная точка?

Диагностируй медленную страницу, проходя по цепи

1/3
Граничные случаи

Поломка 4 (устаревший кеш сервис-воркера) — это поломка, которая не даёт спать ночами худшим инженерам, потому что она может поймать каждого повторного посетителя за сломанным деплоем. Событие activate сервис-воркера — правильное место для очистки старых кешей: проверь версию кеша, удали всё, что не совпадает, и только потом clients.claim(). Без этого сломанная кешированная оболочка выживает до тех пор, пока пользователи не очистят данные сайта вручную — чего большинство пользователей никогда не делает.

Вспомните перед уходом
  1. 01
    Назови пять канонических поломок, слой и метрику каждой, и почему все пять связаны с зловещей долиной гидратации.
  2. 02
    Для каждой из пяти поломок — каково исправление?
  3. 03
    Почему TTFB 2980 мс делает его наиболее высокоэффективным первым исправлением, даже когда LCP и INP тоже плохи?
Итог

Зловещая долина гидратации — структурный зазор между «нарисовано» и «интерактивно» — объединяющий режим сбоя серверно-рендеренных, клиентски-гидрируемых приложений. Пять канонических поломок каждая расширяет её или происходит внутри неё. Поломка 1 (поздний hero, CSS background-image или с ленивой загрузкой) атакует LCP, задерживая обнаружение на слое парсинга. Поломка 2 (несоответствие гидратации, только-клиентские значения отрендеренные на сервере) атакует CLS через недетерминированность рендеринга. Поломка 3 (мегаморфный встроенный кеш V8, слишком много форм объектов на горячем пути) атакует INP, замедляя перерисовки. Поломка 4 (устаревший кеш сервис-воркера, переживший деплой) атакует корректность, портя состояние, от которого зависит вся цепь. Поломка 5 (синхронная тяжёлая работа в обработчике события перед уступкой) атакует INP, исчерпывая бюджет времени обработки. В каждом случае симптом называет неправильный слой — диагноз требует прохода по всей цепи и нахождения места, где причина действительно живёт.

Связанные уроки
встречается в278
Продолжить восхождение ↑Метод трёх треков: чтение трасс и построение системы мониторинга
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources5
expand
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05

Trademarks belong to their respective owners. Editorial reference only.