Мобильный PageSpeed нашего сайта показывал 69 из 100: FCP 3,4 секунды, LCP 5,5 секунды, SI 5,2 секунды при TBT 40 миллисекунд и CLS 0. Совет "сожмите картинки" тут ничего не дал бы: вес страницы был ни при чём, мешала цепочка задержек. Разбираем замер по шагам и объясняем, что сделали.
Проверка скорости обычно превращается в список типовых советов: сожмите картинки, включите кэш, уберите лишние скрипты. Беда в том, что советы одинаковые для любого сайта, а причины медленной загрузки у каждого свои. У нас, например, картинки были ни при чём вообще. Мы разобрали собственный отчёт целиком вместо того, чтобы применять стандартный набор наугад, и записали ход разбора для тех, у кого отчёт выглядит похоже.
Что означают буквы в отчёте
FCP, First Contentful Paint - момент, когда браузер впервые что-то нарисовал на экране: текст, фон, любую видимую часть страницы. LCP, Largest Contentful Paint - момент отрисовки самого крупного видимого элемента, обычно заголовка, картинки или блока текста. Это главная метрика ощущения "сайт загрузился", потому что именно её человек оценивает боковым зрением.
SI, Speed Index - как быстро в среднем заполняется видимая область экрана, число тем ниже, чем быстрее контент проявляется целиком. TBT, Total Blocking Time - сколько миллисекунд суммарно главный поток браузера был занят настолько, что не успевал реагировать на клики. CLS, Cumulative Layout Shift - насколько сильно элементы прыгают, пока страница догружается: у нас он был 0, макет не двигался.
Для ощущения скорости первыми смотрят на LCP и CLS: их видно глазами. TBT важен, если на странице есть с чем взаимодействовать в первые секунды. FCP и SI больше нужны как техническая опора для диагностики. Пороги для этих метрик задаёт Google - официальное описание в документации Search Central, разбор всех метрик - в статье про LCP, INP и CLS.
Как найти LCP-элемент, а не гадать
Как понять, что именно тормозит - гадать по картинке или смотреть в отчёт? Гадать не нужно: отчёт называет элемент прямо, в разделе диагностики есть строка с указанием, какой узел разметки браузер выбрал крупнейшим. У нас это оказался не рисунок, а текст - подзаголовок первого экрана.
Причина простая. На десктопе рядом с заголовком стоит крупная иллюстрация, но на мобильном экране она скрыта правилом display: none. У скрытого элемента нет отображаемого бокса, и браузер не может выбрать его крупнейшим отрисованным - даже если файл картинки давно загружен. Значит и чинить нужно было не вес изображения, а всё, что задерживает появление текста: файл стилей и шрифт.
Что уже было в порядке - и как мы это проверили
Прежде чем что-то чинить, стоит убедиться, что базовые вещи уже работают: иначе легко потратить день на правку симптома вместо причины. У нас в порядке были кэш страниц, который отдаётся с диска, а не пересобирается на каждый запрос, включённое сжатие gzip, статика с заголовком Cache-Control на год и работающий протокол HTTP/2.
Последний пункт стоит проверять честно, а не на глаз. Локальный curl в типовой сборке не умеет HTTP/2 и всегда покажет версию 1.1, даже если сервер прекрасно отдаёт второй протокол. Надёжная проверка через openssl: команда openssl s_client -alpn h2,http/1.1 -connect домен:443 в ответе прямо показывает, какую версию согласовали браузер и сервер. Прогнали оба способа: ограничена была утилита, а не сервер.
Из чего складывалась цепочка ожидания
Когда база в порядке, а скорость всё равно упирается в отрисовку, дальше смотрят на цепочку событий до первого пикселя текста. У нас она выглядела так: браузер открывает соединение, получает HTML, находит в нём ссылку на файл стилей с чужого домена, ждёт ответ. Из файла стилей достаёт ссылку на шрифт с ещё одного чужого домена, снова ждёт. И только после этого может отрисовать текст нужным шрифтом. Каждое звено добавляет отдельное DNS-соединение и отдельный сетевой запрос, а картинки в этой цепочке не участвуют вовсе.
Google Fonts устроен в два прыжка подряд: сначала домен со стилями отдаёт описание шрифта, и только затем идёт запрос к домену с файлами начертаний. Общий разбор техник ускорения - в статье как ускорить сайт.
Правка первая: свои шрифты вместо Google Fonts
Мы скачали исходные файлы шрифтов, урезали их под кириллицу с типографикой - буквы, цифры, знак рубля, стрелка, галочка, неразрывный дефис - и собрали свой файл описаний у себя. Получилось 8 файлов на 135 КБ против 474 КБ у нарезки Google: экономия за счёт того, что на каждое начертание теперь один файл вместо двух форматов.
Описания шрифтов печатаются прямо в HTML, а предзагружаются только два начертания, которые видны на первом экране. Остальные подключаются, но браузер не тратит время на них заранее. Символ рубля, стрелка и галочка в исходных файлах Google не нашлись вовсе - это не потеря нарезки, браузер и раньше подставлял их из системного шрифта. Подробный разбор выбора и подключения шрифтов - в статье про шрифты для сайта.
Правка вторая: критический CSS инлайном
Второй чужой домен убрать было сложнее: сам файл стилей нужен любой странице, отказаться от него нельзя. Решение - вынести правила первого экрана прямо в HTML, это и называется критическим CSS, а основной файл стилей подключить неблокирующим способом с запасным вариантом для браузеров без JavaScript. Тогда браузеру не нужно ждать файл стилей, чтобы показать текст: нужные правила уже в разметке.
Слепок правил снимали на каждом типе страницы и на двух ширинах экрана: то, что критично для карточки товара, не совпадает с тем, что критично для главной, а мобильная вёрстка использует не все те же правила, что десктопная.
Третья и четвёртая правки: счётчик и картинка без спешки
Оставались два источника лишней нагрузки, которые к тексту отношения не имели, но мешали. Счётчик посещаемости загружался сразу в разметке и занимал часть времени в самом начале, хотя в этот момент человеку важен текст на экране, а не аналитика. Запуск счётчика перенесли на момент после отрисовки страницы либо на первое действие человека - раньше сайт для него ещё не готов, и считать посещение рано.
С картинкой было проще: hero-иллюстрация на мобильном скрыта, но грузилась принудительно с атрибутом eager, то есть браузер честно качал байты рисунка, который человек физически не мог увидеть. Сменили атрибут на loading="lazy": у скрытого элемента нет бокса во вьюпорте, значит браузер и не станет запрашивать файл, пока рисунок не понадобится.
Чем за это платят
Инлайн критического CSS вместе с описаниями шрифтов добавил около 7 КБ в сжатом виде на каждую страницу: HTML вырос с 23 до 31 КБ. Заметная прибавка. Внешний файл браузер скачал бы один раз и брал из кэша, а инлайн едет заново на каждой странице: для холодного визита, который и меряет PageSpeed, это выигрыш, а для читателя пяти страниц подряд - небольшая переплата. Мы сознательно выбрали холодный визит: именно с него начинается знакомство с сайтом у нового посетителя.
Что проверить у себя за 20 минут
Короткий чек-лист для отчёта, где в LCP тоже стоит текст:
- Открыть отчёт PageSpeed для мобильной версии и найти LCP-элемент в разделе диагностики - это прямое указание, а не догадка.
- Если LCP-элемент - текст, проверить цепочку до отрисовки: сколько внешних доменов опрашивает браузер до шрифта - стили, сам шрифт, аналитика.
- Проверить протокол через openssl, а не через curl:
openssl s_client -alpn h2,http/1.1 -connect домен:443. - Убедиться, что статика отдаётся с длинным Cache-Control и включённым сжатием - это делается один раз и почти не ломается само.
- Проверить атрибут loading у изображений, скрытых на мобильном экране: eager на невидимом элементе тратит трафик и время впустую.
- Проверить, в какой момент запускаются счётчики аналитики - до первой отрисовки или после.
Набор честных инструментов для замера собран в статье как проверить скорость сайта: без надёжного способа измерить результат чек-лист выше нечем подтвердить.
Итог: считать по отчёту, а не по интуиции
Мобильный PageSpeed 69 сложился у нас не из веса страницы, а из очереди задержек перед отрисовкой текста: два чужих домена ради шрифтов, блокирующий файл стилей и пара второстепенных запросов не вовремя. Четыре точечные правки подняли показатели без единого килобайта экономии на картинках. Плата за это реальная - HTML стал тяжелее на 8 КБ, но для холодного мобильного визита размен себя оправдал.
Если у вас похожий отчёт и в LCP тоже текст, начните с честного замера через инструменты из статьи как проверить скорость сайта. А как та же логика диагностики сработала на производственном сайте - в кейсе ускорение сайта строительной компании с 6,2 до 1,4 секунды: причины и правки там были другими.

