100 баллов в PageSpeed: что мы для этого изменили

Время загрузки — фактор ранжирования, но обычные советы помогают редко. Эта статья описывает, что мы действительно изменили на собственном сайте, какая мера сколько дала и где мы свернули не туда.

Светящаяся фигура ускоряется вправо, а за ней растворяются тёмные блоки

Самое главное вкратце

  • Самый большой единичный выигрыш пришёл не от уменьшения файлов, а от замены библиотеки в 458 КБ на 6 КБ собственного кода.
  • Вторая по величине причина — наполовину настроенное сжатие: сервер сжимал только HTML, а не CSS и JavaScript.
  • Скачок макета со значением 1 стоил 24 балла — его вызвал догружаемый CSS, который срабатывал только после первого построения картинки.
  • Что дало меньше всего: форматы изображений. Что дало больше всего: убирать лишнее.

Исходное значение было 58 из 100 на телефоне. Это неплохое значение для сайта с 3D-эффектом в шапке, но такое, за которое Google в мобильном поиске заметно наказывает. В итоге вышло 100 баллов на компьютере и 98 на телефоне, при тех же 100 за доступность.

Дальше идёт не общий чек-лист, а фактический ход событий — включая места, где мы ошиблись.

Светящаяся фигура ускоряется вправо, а за ней растворяются тёмные блоки
Быстрой страница становится не от оптимизации, а от отказа от лишнего.

Исходная ситуация

Измерение (мобильное)допосле
Производительность5898
Доступность95100
Первое построение картинки6,1 с1,4 с
Крупнейший элемент виден11,1 с2,1 с
Передано всего298 КБ184 КБ
из них JavaScript121 КБ5 КБ

Пять вмешательств, которые действительно считались

1. Заменить библиотеку, а не оптимизировать

Шапка показывает облако частиц в 3D. Для этого работала известная графическая библиотека — 458 КБ после уменьшения. Измерение показало, что 51 КБ из них вообще никогда не выполнялись.

Решающим был взгляд на вопрос, сколько нам действительно нужно. Это оказалось одиннадцать блоков: рендерер, сцена, камера, геометрия, материал и пара вспомогательных классов. Всё это можно запрограммировать напрямую к графическому интерфейсу браузера.

Результат: 458 КБ превратились в 6 КБ. Отображение идентично — мы переняли те же шейдеры.

Внимание Две детали при этом нужно воспроизвести, иначе результат выглядит неправильно: библиотека пересчитывает цвета из hex-формата в линейный свет и смешивает аддитивно с предумноженной альфой. Без обоих наше облако частиц выглядело заметно ярче, чем раньше.

2. Сжатие было включено лишь наполовину

В конфигурации сервера сжатие стояло на «вкл» — но строка, задающая, какие типы файлов сжимать, была закомментирована. Это настройка по умолчанию у многих дистрибутивов. Результат: сжимался исключительно HTML.

Значит, графическая библиотека шла по каналу несжатой. После включения: 1243 КБ превратились в 251 КБ. К тому же мы теперь кладём рядом заранее рассчитанные сжатые версии, чтобы сервер не пересчитывал их при каждом запросе.

Затраты: две строки конфигурации. Действие: почти мегабайт на каждый первый вызов.

3. Убрать библиотеку анимации целиком

Для появлений при прокрутке работала ещё одна библиотека, 114 КБ. Измерение вдобавок указало на неё как на виновницу принудительных пересчётов макета — она во время прокрутки запрашивала геометрию и вынуждала браузер пересчитывать макет посреди движения.

Заменена на IntersectionObserver, который лишь ставит класс. Само движение делает CSS. На 114 КБ меньше, никаких пересчётов, около 40 строк собственного кода.

4. Фавикон весил 205 КБ

Мелочь с удивительным действием, потому что она загружается очень рано. Заменена на SVG-файл в 6 КБ, созданный из имеющегося логотипа.

А ты знаешь?

Для показа в результатах поиска Google SVG-фавикон не помогает — Google принимает там только растровые форматы, и картинка должна быть квадратной со стороной, кратной 48 пикселям.

Значит, кто закладывает только SVG, получает в результате поиска серую заглушку вместо собственного логотипа. Указывать оба рядом — правильный путь.

5. Запрашивать геометрию в кадре анимации

Скрипт при каждом событии прокрутки считывал общую высоту документа. Это свойство браузер не может ответить по памяти — ради него он должен заново пересчитать макет всей страницы, посреди прокрутки.

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

Ошибка, которая стоила 24 балла

Слева плотная стопка серых блоков, вправо остаётся лишь несколько светящихся
Решает то, что остаётся, а не то, насколько хорошо остальное сжато.
Из практики

Чтобы избавиться от последнего блокирующего запроса, мы разделили таблицу стилей: часть, нужная для видимой области, попадала прямо в документ, остальное догружалось. Распространённый подход.

Разрез прошёл по метке в исходном файле, за которой мы предполагали видимую область. На деле за ней стояли правила для логотипа в шапке, для отступов под ним и для появлений. Значит, страница строилась без них и через секунду сдвигалась на место.

Результат: Cumulative Layout Shift равный 1,0 — и тем самым 76 вместо 100 баллов на компьютере. Особенно неприятно: локально с придушенным каналом значение было 0, потому что таблица стилей приходила там достаточно рано. Ошибка была видна только на быстром соединении.

Урок: либо вся таблица стилей в документ, либо никакой. Частичная вставка требует, чтобы ты точно знал, какое правило нужно в видимой области, — а на растущей странице это не знаешь навсегда.

Совет При подозрении на скачки макета измеряй без придушенного канала. Инструмент проверки с симулированным мобильным соединением подаёт файл достаточно рано и скачок не показывает. Кто измеряет только так, считает проблему решённой.

Что дало мало

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

Форматы изображений. На нашей главной почти нет картинок — логотип это SVG-файл. Где картинки встречаются, преобразование, разумеется, оправдано; как главный рычаг оно годится только для страниц, насыщенных изображениями.

Дальше уменьшать шрифты. Мы держим два семейства шрифтов у себя и предзагружаем нужные для видимой области. Дальнейшая оптимизация была бы возможна, но значение не двигает.

Местоположение сервера. Многократно рекомендуется, в нашем случае нерелевантно: время до первого байта уже было 20 миллисекунд. Кто там уже хорош, ничего не выигрывает от сети распространения.

Порядок для повторения

  1. Измерить, прежде чем что-либо менять. Мобильное и десктоп отдельно, значения записать.
  2. Найти самый большой переданный файл. Почти всегда это JavaScript. Вопрос не в том, как его уменьшить, а в том, нужен ли он.
  3. Проверить сжатие. Не включено ли оно, а для каких типов файлов.
  4. Посчитать блокирующие запросы. Каждый файл таблицы стилей в шапке задерживает первое построение картинки.
  5. Проверить скачки макета без придушенного канала. Тот единственный тест, которого у нас не хватало.
  6. После каждого изменения измерять заново. Иначе в конце не знаешь, что подействовало.
Prompt
Помоги мне перевести отчёт PageSpeed моей страницы в
последовательность. Будь строг; ничего не хвали.

Мои измерения:
- Мобильное: [баллы], десктоп: [баллы]
- LCP, TBT, CLS по каждому устройству: [значения]
- Крупнейшие переданные файлы с размером: [список]
- Запросы, блокирующие рендеринг: [список]
- Сообщения из отчёта: [вставить текст]

О странице:
- Как она построена: [CMS / статическая / конструктор]
- Нужен ли JavaScript для видимого содержимого? [да/нет]
- Как поставляется CSS? [внешне / заранее / частично заранее]

Задачи:
1. Отнеси каждое сообщение к причине и скажи, на какую метрику
   оно влияет — LCP, TBT или CLS.
2. Отсортируй меры по действию на затраты. Назови у каждой,
   на сколько баллов она реалистично двигает и почему.
3. Назови меры из отчёта, которые при моём типе постройки
   практически ничего не дают, — и обоснуй, а не просто их
   опусти.
4. По каждому большому файлу JavaScript сначала спроси, нужен
   ли он, прежде чем предлагать уменьшение.
5. Укажи, если CSS поставляется заранее лишь частично, и
   объясни, почему для CLS это может быть хуже, чем вовсе нет.
6. Назови, что мне после каждого изменения стоит измерять
   заново.

Не выдумывай измерения.

Вывод

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

Путь туда в нашем случае вёл через один повторяющийся вопрос: нужно ли нам это? Пять из шести вмешательств состояли в том, чтобы что-то убрать, а не что-то добавить.

Частые вопросы

Как достичь 100 баллов в PageSpeed Insights?

У большинства сайтов через три шага: убрать или заменить самый большой файл JavaScript, действительно включить сжатие для CSS и JavaScript и устранить скачки макета. Форматы изображений и местоположение сервера редко бывают узким местом.

Насколько важно время загрузки для ранжирования Google?

Это подтверждённый фактор, но не сильный — содержание и релевантность весят больше. Больший эффект косвенный: медленные страницы чаще бросают, и это поведение входит в оценку.

Что такое Cumulative Layout Shift и как его устранить?

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

Стоит ли встраивать CSS в HTML?

При небольших таблицах стилей да, но тогда полностью. Частичная вставка с догрузкой остального экономит один запрос и взамен наживает скачки макета, как только правило для видимой области отсутствует. У нас это было 7 КБ в упаковке — ради этого полная вставка оправдана.

Сколько даёт отказ от библиотек?

В нашем случае — самую большую отдельную статью: 458 КБ графической библиотеки превратились в 6 КБ собственного кода, плюс 114 КБ библиотеки анимации в ноль. Оправдано ли это, зависит от того, сколько библиотеки ты на самом деле используешь — измерение показывает неиспользуемый JavaScript.

Маркетинг, который настраивается сам

Бета Studio Engine уже открыта. Забронируй место и участвуй в развитии с самого начала.

Присоединиться к бете →
← Назад к обзору