惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Security @ Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
Hacker News: Ask HN
Hacker News: Ask HN
L
LangChain Blog
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
H
Heimdal Security Blog
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
Y
Y Combinator Blog
The Cloudflare Blog
N
Netflix TechBlog - Medium
云风的 BLOG
云风的 BLOG
F
Full Disclosure
TaoSecurity Blog
TaoSecurity Blog
人人都是产品经理
人人都是产品经理
P
Proofpoint News Feed
T
Troy Hunt's Blog
H
Hacker News: Front Page
MongoDB | Blog
MongoDB | Blog
MyScale Blog
MyScale Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
CERT Recently Published Vulnerability Notes
S
SegmentFault 最新的问题
T
The Exploit Database - CXSecurity.com
S
Security Affairs
H
Help Net Security
美团技术团队
小众软件
小众软件
Security Latest
Security Latest
Microsoft Azure Blog
Microsoft Azure Blog
P
Privacy International News Feed
G
Google Developers Blog
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
U
Unit 42
Hacker News - Newest:
Hacker News - Newest: "LLM"
SecWiki News
SecWiki News
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 聂微东
A
Arctic Wolf
Microsoft Security Blog
Microsoft Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - Franky
M
MIT News - Artificial intelligence

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
LCP под микроскопом: как выжать максимум из самой важной метрики Google
mironov_niko · 2026-05-18 · via Все публикации подряд на Хабре

Уровень сложностиПростой

Время на прочтение13 мин

Охват и читатели490

Кейс

Довольно многие, кто близок к миру web разработки, не раз слышали про метрики web-vitals. По-настоящему значимыми они стали в середине 2021 года — в этот период Google официально стал учитывать метрики в ранжировании для мобильного поиска. С тех пор многие компании стремятся добиться хороших показателей метрик web-vitals. И, пожалуй, самая важная из этих метрик — LCP.


Привет! Меня зовут Николай, я — frontend-разработчик в компании Иви. В зоне моей ответственности как раз и лежит web-версия онлайн-кинотеатра. И в четвертом квартале 2025 года команда web решила сосредоточить ресурсы на метрике LCP. Что такое web-vitals в целом и LCP в частности?

Оглавление

Метрики web-vitals — что это?

Web-vitals — это инициатива Google, которая выделяет ключевые метрики для оценки пользовательского опыта на сайте. Если раньше были десятки сложных показателей, то web-vitals фокусируется на нескольких, самых важных.

Цель — дать единый, понятный язык для разработчиков, SEO-специалистов и руководителей, чтобы оценить, насколько быстро, отзывчиво и стабильно работает сайт для реальных пользователей.

Текущие ключевые метрики web-vitals

Ключевая тройка метрик меняется каждые несколько лет. Сейчас (2026) это:

  1. LCP (Largest Contentful Paint) — «Как быстро загружается основное содержимое?» (Метрика загрузки)

  2. INP (Interaction to Next Paint) — «Как быстро сайт реагирует на клики, тапы, нажатия клавиш?» (Метрика отзывчивости). (Примечание: заменил FID в 2024 году)

  3. CLS (Cumulative Layout Shift) — «Насколько стабильно отображается страница, не "прыгает" ли контент?» (Метрика визуальной стабильности)

Почему им уделяют столько внимания?

  • Пользовательский опыт: Прямая связь с удовлетворенностью

  • SEO: Являются ранжирующим фактором в поиске Google

  • Бизнес-метрики: Хорошие web-vitals коррелируют с более высокой конверсией и вовлеченностью

Подробнее про метрику LCP

Простыми словами: LCP измеряет, через какое время самый большой и заметный элемент в видимой области экрана (viewport) становится полностью отрисованным. Это момент, когда пользователь видит, что «страница уже грузится» и появляется главный контент.

Что считается LCP-элементом?

  • Изображения (<img><image> внутри <svg>)

  • Постер-изображения внутри видео (<video> с poster)

  • Элементы с фоновым изображением, загруженным через url() (css свойство background-image)

  • Блочные элементы (<div><p><h1>) с текстовым узлом

Примеры с сайта Иви:

для главной страницы LCP-элементом является постер в слайдере:

для доступного контента LCP-элементом является постер в плеере:

пример, где LCP-элементом является текстовый узел (заголовок страницы):

Что НЕ считается LCP-элементом?

  • Элементы, которые находятся за пределами видимой области

  • Слишком мелкие элементы — выбирается всегда самый большой

  • Анимированные или меняющиеся элементы

Пороги оценки LCP:

  • Хорошо (Good): ≤ 2.5 секунды

  • Требует улучшений (Needs Improvement): 2.5 – 4.0 секунды

  • Плохо (Poor): > 4.0 секунды

Инструменты для мониторинга LCP

Основным инструментом для мониторинга web-vitals метрик являются так называемые CrUX (Chrome User Experience) отчеты, которые строит Google. Эти отчеты находятся в открытом доступе и можно смотреть состояние метрик в принципе для любого сайта. Вот ссылка-пример такого отчета для сайта Иви:

https://cruxvis.withgoogle.com/#/?view=loadingperf&url=https%3A%2F%2Fwww.ivi.ru%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s

В качестве упражнения, попробуйте посмотреть CrUX отчеты ваших любимых сервисов.

Главная панель метрики LCP

Главная панель метрики LCP

Тут можно обратить внимание на вкладку Controls — она позволяет гибко настраивать вывод графика метрик. Чем именно пользуется наша команда:

  • В фильтре Data мы глобально ориентируемся на Origin — данное значение показывает LCP для всех страниц сайта в целом

  • В фильтре Device — в первую очередь ориентируемся на мобильные устройства (Phone)

  • И также нас интересует 75 перцентиль — это показатель, сколько страниц сайта имеют определенное значение метрики

Решение сосредоточить силы команды было принято исходя как раз из этого отчета, и основной нашей задачей было улучшить LCP для мобильных устройств, потому что значение метрики «подбиралось» к желтой зоне (>2.5 секунд). Почему также не десктоп? А для десктопа у нас значение метрики было с хорошим запасом (по данным CrUX отчетов в районе ~1800ms):

И еще одной причиной внимания именно к мобильным значениям метрики является инициатива Google, называемая mobile-first-indexing. Это подход, при котором для сканирования, индексации и ранжирования сайтов используется в первую очередь их мобильная версия, а не десктопная. Это означает, что контент, структура и технические параметры (скорость, адаптивность), доступные на смартфонах, определяют место сайта в поисковой выдаче. Подробнее тут — https://developers.google.com/search/docs/crawling-indexing/mobile/mobile-sites-mobile-first-indexing?hl=ru

Препарируем метрику LCP — из чего она состоит?


Для дальнейшего понимания и поиска узких мест надо разобраться, из чего же состоит метрика LCP и что именно показывают ее составляющие:

Метрику LCP составляют четыре «подметрики» в порядке их подсчета при загрузке страницы с LCP-элементом:

  1. TTFB — Time to first byte — время от начала навигации до получения первого байта HTML-документа от сервера. Эта метрика показывает скорость работы бэкенда и сети. Важно отметить, что эта метрика также считается отдельной самостоятельной метрикой web-vitals, но при этом входит в конечный LCP

  2. Resource Load Delay — задержка начала загрузки LCP-элемента. Это время между TTFB и моментом, когда браузер фактически начал скачивание LCP-элемента. Большая задержка означает, что более важный ресурс ждал, пока скачаются менее важные

  3. Resource Load Duration — собственно время скачивания LCP-элемента. Тут все просто. На значение этой метрики влияет размер изображения, его степень сжатия, скорость работы сети и наличие кэша

  4. Element Render Delay — это время между окончанием загрузки элемента и его финальной отрисовки на экране. На эту метрику может влиять опять же размер изображения (от этого зависит скорость его декодирования на CPU, особенно для более слабых по сравнению с ПК мобильных устройств); ожидание основного потока (Main Thread); ожидание стилей

Очень удобно, что CrUX отчет также предоставляет графики этих составляющих LCP, где можно отдельно проанализировать изменение в течение времени каждой из них:

Анализ и выявление возможностей для оптимизации

Сейчас по логике я должен рассказать, как мы проводили анализ и выявляли куда двигаться, но я сделаю небольшое отступление. Параллельно с тем, что команда взяла задачу по улучшению метрики, один из наших коллег решил сделать эксперимент. Исторически сложилось так, что картинки на сайте Иви в большинстве своем были в формате JPEG, тем временем как формат WebP уже обзавелся внушительной поддержкой современными браузерами. Было принято решение провести эксперимент с заменой формата с JPEG на WebP. Для замеров использовался стенд — пустая страница с одним вариантом картинки из двух: A) JPEG B) WebP Результаты отражены в таблице ниже:

Перцентили LCP

JPEG

WebP

Разница в процентах

p50 LCP (ms)

1628

1284

-21.1% 

p75 LCP (ms)

1752

1344

-23.3% 

p95 LCP (ms)

2140

1396

-34.8% 

Увидев такие хорошие результаты, было принято решение уже на самом сайте Иви заменить формат картинок, являющихся LCP-элементом (см. примеры с сайта Иви выше): на Главной странице сайта и на карточках контента. По итогу эксперимента увидели улучшение метрики для Главной страницы на десктопной версии на 45ms, на мобильной версии — 35ms. На карточках изменений не было, но результат в целом нас устроил и открыл дорогу к дальнейшим поискам возможностей оптимизации LCP. Увы, не всегда достаточно просто внедрить новую технологию, чтобы улучшить метрики. Так что копнем глубже.

Разобравшись с теоретической частью и вооружившись инструментами мониторинга, мы в первую очередь провели анализ LCP на сайте с большим вниманием к карточкам контента в контексте мобильной версии, так как карточки контента — это большинство страниц сайта Иви, и нам очень важна их скорость работы. С результатами замеров можно подробно ознакомиться в таблице ниже:

Тестируемое окружение — прод сайта Иви, проблемный web-mobile, сетевой кэш отключен, средние результаты по 5 замерам LCP в ms

«Легенда» таблицы:

  1. TTFB: Time To First Byte

  2. RLD: Resource Load Delay

  3. RLDura: Resource Load Duration

  4. ERD: Element Render Delay

  5. LCP Total: TTFB + RLD + RLDura + ERD

Тип страницы

Троттлинг

TTFB

RLD

RLDura

ERD

LCP Total

Доступный к просмотру контент

Нет

384

26

108

315

832

4xCPU + Slow 4G

381

343

2286

2100

5110

6xCPU + Slow 4G

1268

265

1843

2153

5529

20xCPU + Slow 4G

3060

365

5426

2205

11055

4xCPU + 3G

453

1750

8339

6646

17188

6xCPU + 3G

945

1784

9215

5663

17606

20xCPU + 3G

3125

2301

7598

5120

18144

Закрытый подпиской или покупкой контент

Нет

380

16

179

279

854

4xCPU + Slow 4G

2509

354

3128

707

6698

6xCPU + Slow 4G

4250

338

3095

781

8464

20xCPU + Slow 4G

23129

512

2896

1187

27724

4xCPU + 3G

1783

3023

11401

2156

18362

6xCPU + 3G

293

4220

10047

5255

19814

20xCPU + 3G

40548

1864

10425

3194

56030

Так называемый «фейк» — карточки для SEO

Нет

1940

11

140

1616

3706

4xCPU + Slow 4G

11054

403

1770

9995

23223

6xCPU + Slow 4G

17154

413

1737

10283

29587

20xCPU + Slow 4G

68414

740

1579

16769

87502

4xCPU + 3G

16351

1937

6607

33641

58535

6xCPU + 3G

26734

1718

6605

34438

69494

20xCPU + 3G

97682

2141

6256

45391

151470

Главная страница

Нет

2171

40

103

84

2400

4xCPU + Slow 4G

1373

82

2745

2047

6257

6xCPU + Slow 4G

902

160

5675

32

6768

20xCPU + Slow 4G

854

206

5176

233

6469

4xCPU + 3G

843

1507

14197

2283

18828

6xCPU + 3G

844

1675

16557

482

19557

20xCPU + 3G

997

1336

13656

3317

19304

Также для облегчения анализа были сделаны дополнительные задачи (не направленные на прямое улучшение LCP). Основной задачей стало добавление графика разбивки метрики LCP в Grafana. Этот график строится на основе отправляемых данных LCP в нашу аналитическую систему. Основное отличие от графиков в CruX отчетах заключается в том, что этот график обновляется в режиме реального времени, что обеспечивает команде веба непрерывный мониторинг и анализ метрики, и в случае негативных изменений позволяет оперативно реагировать на ухудшение. Как пример — несколько раз при проблемных релизах мы очень быстро выявляли проблему и откатывали релиз, не дожидаясь пересчета метрики со стороны Google. Скрин для понимания:

Дополнительно был проведен ручной анализ DOM дерева на предмет оптимизаций LCP.

По результатам анализа были сформулированы и реализованы следующие задачи (помимо упомянутого выше эксперимента с WebP):

  • До начала работ по LCP на карточках контента LCP-элементом у нас являлись теги div с background-image. Гипотеза состояла в том, что если перевести LCP-элемент на тег image и обвесить его специальными атрибутами (fetchpriority = high и loading = eager), то можем получить некоторое улучшение LCP. Атрибут fetchpriority со значением high как бы говорит браузеру — этот ресурс надо загрузить как можно скорее, а атрибут loading со значением eager прямо указывает, что изображение должно загрузиться немедленно, в отличие от значения lazy. По итогам никакого улучшения не было выявлено, LCP остался в тех же значениях.

  • Далее решили продолжать копать тему с тегом img и решили расширить этот тег тегом picture. Тут гипотеза состояла в том, что у нас что для десктопа, что для мобильных устройств отдавалась одна и та же по размерам картинка в довольно большом разрешении. Решили добавить респонсивные постеры с помощью тега picture. Целями опять стали LCP картинки на Главной и на карточках контента. По результатам получили небольшое улучшение LCP (~35-50ms) на всем сайте.

  • Благодаря задаче с выводом составляющих LCP в графане заметили, что Element render Delay довольно высок, чтобы быть нормой. Решили копать в эту сторону дальше. Одной из предполагаемых причин было то, что у нас слишком загруженный Main Thread, но раскопки с использованием Perfomance в Chrome ни к чему не привели. Тогда решили зайти с другой стороны, не разбираться в кишках всего приложения и искать проблему там, а создать тестовый стенд и начать пошагово навешивать туда функционал, который в теории может замедлять Element Render Delay.

Возможно, тут возникнет вопрос — а было ли что-то по TTFB? Ответ — да, коллеги из нашей команды параллельно работали над улучшением кэширования для всего сайта. Вкратце, это ускорило TTFB и соответственно LCP по данным из аналитической системы. Впрочем, это тема для отдельной статьи, и возможно в будущем мы про это расскажем (увлекательная получится история, следите за обновлениями!).

Прицельно бьем в Element Render Delay


Вследствие неудачи ресерча ERD, решили сделать стенд — начать с простого html файлика (без экосистемы React) с картинкой (которая будет считаться как LCP-элемент) и постепенно добавлять туда разный функционал, который в теории может ухудшать или улучшать время Element Render Delay. Условия эксперимента — mobile, без учета троттлинга процессора и сети, изначально используется картинка с нашего CDN; также создан вспомогательный скрипт в head, который находит LCP-элемент и вытаскивает из него Element render delay. Далее делаем 15 замеров (перезагрузок страницы) — и скрипт выведет средний ERD. Эксперименты и результаты собраны в табличке под катом (уж очень внушительной она оказалась):

Эксперименты и результаты

Эксперимент/гипотеза

Описание гипотезы

Результат ERD по 15 замерам

Вывод

картинка в теге img в формате

JEPG без атрибутов оптимизации

посмотреть, как считается ERD, когда нет ничего в теории блокирующего ERD

 📊 Средний LCP: 284 мс

⏱️ Средний ERD: 28 мс

📈 Средний ERD%: 10,3%

✅ ОТЛИЧНО: Нормальный уровень ERD

Без блокирующих в теории фич ERD в рамках нормы

тегу img добавлены атрибуты размеров

возможно добавление таких атрибутов ускорит отрисовку картинки браузером

📊 Средний LCP: 568 мс

⏱️ Средний ERD: 344 мс

📈 Средний ERD%: 19,3%

✅ ОТЛИЧНО: Нормальный уровень ERD

Улучшения ERD не выявлено

картинка с другого источника, размеры те же

предполагается, что есть проблемы с нашим CDN

В пределах нормы

По сравнению с другим источником наш CDN отдает картинку быстрее

конвертация JPEG в WebP

проверить, как повлияет изменение формата на ERD

📊 Средний LCP: 297 мс

⏱️ Средний ERD: 32 мс

📈 Средний ERD%: 12,0%

✅ ОТЛИЧНО: Нормальный уровень ERD

На ERD изменение формата на WebP существенно не влияет

добавление атрибутов fetchpriority=high и loading=eager у тега img

проверить, оказывают ли эти атрибуты влияние на ERD

📊 Средний LCP: 281 мс

⏱️ Средний ERD: 33 мс

📈 Средний ERD%: 11,9%

✅ ОТЛИЧНО: Нормальный уровень ERD

На ERD добавление атрибутов не оказывает эффекта

добавление в head медленных шрифтов 

медленные шрифты могут тормозить ERD

📊 Средний LCP: 281 мс

⏱️ Средний ERD: 31 мс

📈 Средний ERD%: 11,6%

✅ ОТЛИЧНО: Нормальный уровень ERD

Медленные шрифты не тормозят ERD

добавление "тяжелых" css вычислений в head

тяжелые вычисления css могут тормозить ERD

📊 Средний LCP: 280 мс

⏱️ Средний ERD: 29 мс

📈 Средний ERD%: 10,9%

✅ ОТЛИЧНО: Нормальный уровень ERD

Также критичного ухудшения ERD не замечено

добавление тяжелого скрипта для создания long task

тяжелые long task могут тормозить ERD

ERD ухудшился

long task ухудшают ERD примерно на время их выполнения

добавление микротасок

Множество микротасок могут ухудшать ERD.

Эксперимент запускался сначала с 60 микротасками, потом с 100, потом с 1000, потом без микротасок

В пределах нормы

Микротаски никак не влияют на ERD — на разных кол-вах микротасок изменений ERD нет вообще

добавление счетчиков GTM, Яндекс Метрики и тп как на сайте на КК

выполнение скриптов аналитики может тормозить ERD

В пределах нормы

Счетчики аналитики никак не влияют на ERD

добавление бандла css

проверить, оказывают ли влияние наши бандлы на ERD; Добавление в том же порядке, что и на кк (в head)

В предалх нормы

бандл css не влияет на ERD

добавление бандла js

В пределах нормы

внезапно, но бандл js + бандлы для его работы (react ecosystem, web cypher) не влияют на ERD

добавление бандла плеера css

В пределах нормы

На ERD css бандл плеера не влияет

добавление бандла плеера js

В пределах нормы

Тут влияния бандла на ERD также нет

Блок бандлов через Charles

Посмотреть как влияет блокировка бандлов на ERD

Негативные изменения ERD

Если заблокирован только бандл css — сильно ухудшается ERD (на время блокировки примерно)

Если заблокирован только бандл js — LCP в целом считается и отправляется по лого в шапке

Если заблокированы оба бандла — LCP не считается ни в Perfomance tab, ни в расширении web-vitals хрома, не отправляется в грут после взаимодействия со страницей; отправляется кастомный LCP

Зовем на подмогу — дополнительные эксперименты при помощи Charles


Из всех экспериментов на стенде «удался» — то есть показал явное влияние на ERD — эксперимент с блокировкой загрузки основных бандлов через Charles.

Блокировка основного js бандла

Подробнее опишу кейс, который был найден с помощью Charles. Мы обратили внимание на наши основные js и css бандлы. В них собраны скрипты и стили, которые нужны на всех разделах иви. Далее решили посмотреть, а что происходит, если загрузку этой статики «подвесить» в Charles, и увидели интересное поведение — при блокировке js бандла во вкладке Network у нас также подвисали два css файла для шапки сайта, а также для кнопки «Открыть» в приложении. Нюанс этих блоков в том, что их css лежит рядом с ними, а не в теге head. Это следствие реализации этих компонентов как Lazy-блоков. При этом эти блоки находились ДО блока, внутри которого весь основной контент страницы, включая LCP-элемент. Для понимания скрин DOM до оптимизации:

  1. Файл со стилями шапки

  2. Блок шапки, генерирующий css рядом с собой

  3. Стили кнопки Открыть в приложении

  4. Враппер, в котором лежит блок с LCP-элементом

И при этом, до тех пор, пока эти два css файла не зарезолвились, мы наблюдали пустую страницу с фоном. Исходя из этого родилась задача — просто перенести эти блоки ниже блока с LCP-элементом, а стилями визуально сделать так, как будто переноса не было. Но к сожалению оказалось, что этот вариант оптимизации в отношении шапки сайта нам не подходит, так как в теории перенос шапки сильно сломает SEO. Пришлось откатить правки и подумать над другим решением. Обратили внимание, что именно Lazy рельсы компонента создают его css файл рядом. Поэтому решили сделать шапку обычным компонентом — стили шапки стали собираться в общем css бандле. Блок кнопки Открыть в приложении оставили после враппера. По итогу это почти простое решение дало очень мощный выхлоп — значительное улучшение метрики LCP на всем сайте в целом и на основных разделах в частности: ~200-250ms для Mobile, ~150-200ms для Desktop. Это подтвердилось как на наших внутренних графиках, так и на CrUX отчетах.

Блокировка основного css бандла

Воодушевленные таким успехом, мы решили повторить эксперимент с подвисанием, только в этот раз с бандлом стилей. В этом кейсе все остальные скрипты и стили продолжали загружаться, но тем не менее, пока css бандл был в состоянии pending, на странице не было видно LCP-элемента. При снятии блокировки в charles LCP-элемент появлялся, а сама метрика, а конкретно ее составляющая Element Render Delay считалась примерно в ТО ЖЕ время, на которое была заблокирована загрузка css бандла. По результатам этого эксперимента родилась задача — сделать так, чтобы css бандл не блокировал рендер DOM дерева, а также добавить critical.css (или skeleton.css), который был бы легковесным и его скачивание занимало гораздо меньше времени, чем скачивание основного бандла. В рамках эксперимента сделали это только для карточек контента и только на мобильной версии сайта, под аб-тестом. По итогу зафиксировали значительное улучшение метрики LCP на mobile (~100-110ms), а конкретно составляющий LCP — Element Render Delay. Другие составляющие LCP без изменений (что, собственно, и ожидалось).

Из желтой зоны в зеленую —  итоги наших оптимизаций


До начала экспериментов по данным CrUX LCP для мобильных устройств подбирался к желтой зоне и даже в определенные временные промежутки попадал в нее, в пике значение было 2521ms. Но в итоге нашими экспериментами удалось снизить это значение на 419ms, до 2102ms по последним данным CrUX, в пересчете на проценты ~17%. Считаем это хорошим результатом как по абсолютным цифрам, так и по относительным. При этом стоит отметить, что мы пришли к выводу, что именно со стороны клиента возможности оптимизации мы исчерпали.

Приведу рекомендации тем разработчикам, которые либо планируют, либо уже занимаются оптимизацией LCP:

  • CrUX и его показатели — ваш основной ориентир

  • Очень удобно настроить на своей стороне инструменты мониторинга — обязательно сделайте это!

  • Нащупайте больные места вашей LCP, используя анализ подметрик — это покажет, в каких местах у вас проблемы. Для нас это стали показатели Element Render Delay и TTFB

  • Следите за LCP-картинками — мир веб-разработки развивается стремительно, даруя новые возможности для оптимизации их загрузки

  • Проанализируйте поведение ваших бандлов/скриптов при различных кейсах — велика вероятность их прямого влияния на LCP

На этом мой рассказ подходит к концу. Надеюсь, он был полезен для вас. Желаю вам удачи в ваших экспериментах!