В прошлом разборе о скорости сайта среди проверок был пункт: снимите вес страницы и убедитесь, что сжатие работает. Пункт правильный, проверка простая — и именно на ней мы сами попались. Наш сайт её проходил. Сжатие работало. Просто не то и не для тех.
Эта статья — разбор собственного случая с двумя цифрами: 169,7 КБ до и 76,2 КБ после, при неизменном содержимом страницы.
Проверка, которая врёт
Обычный способ убедиться, что сжатие включено, выглядит так:
curl -s -H "Accept-Encoding: br" -o /dev/null \
-w "%{size_download} байт\n" https://ваш-сайт.com/
Ответ приходит маленький, вы довольны. Проблема в заголовке, который вы только что отправили. Вы попросили исключительно brotli — и сервер, разумеется, дал brotli.
Настоящий Chrome просит другое:
Accept-Encoding: gzip, deflate, br, zstd
Это список того, что браузер умеет, без требования. Выбирает сервер. И 21 августа 2026 наш сервер на этот заголовок отдавал gzip на 169,7 КБ, тогда как brotli той же страницы весил 76 КБ. То есть лучший вариант существовал, лежал рядом и не доставался ни одному живому посетителю.
Правило отсюда одно: замеряйте тем заголовком, который шлёт браузер. Замер с Accept-Encoding: br даёт красивую цифру, которой никто не получает.
curl -s -H "Accept-Encoding: gzip, deflate, br, zstd" -o /dev/null \
-w "размер: %{size_download} байт\n" \
-D - https://ваш-сайт.com/ | grep -i content-encoding
Последняя строка покажет, что реально приехало: br, gzip или ничего.
Две причины, обе неочевидные
Первая: приложение сжало первым. Многие фреймворки сжимают ответ сами, и делают это по умолчанию, без всякой настройки. Дальше ответ попадает на прокси — а тот видит уже сжатый поток и не трогает его. Это правильное поведение: разжимать и пересжимать чужое было бы напрасной работой. Следствие в том, что ваш хорошо настроенный brotli на прокси просто никогда не вызывается.
В нашем случае фреймворк умеет только gzip. То есть цепочка была такая: приложение сжало в gzip → прокси увидел готовое и пропустил → браузер получил gzip. Brotli не участвовал вообще.
Вторая: тот gzip был слабее самого быстрого gzip. Это самая странная часть замера. Мы взяли ту же страницу и сжали локально:
| Способ | Размер |
|---|---|
gzip -1 (самый быстрый уровень) |
143,6 КБ |
gzip -9 (самый сильный) |
111,0 КБ |
| что отдавал сервер | 169,7 КБ |
Сервер проигрывал даже самому слабому уровню на 18%. Причина не в настройках, а в том, как отдаётся современная страница: не готовым документом, а потоком, кусками, по мере того как сервер её собирает. Потоковое сжатие не видит документа целиком и не может использовать повторяемость, которую увидел бы архиватор на готовом файле. Плата за более быстрый первый байт.
Что сделали
Выключили сжатие в приложении полностью. Из контейнера теперь выходит сырой HTML — 788 КБ, и это нормально: этот поток не покидает машины.
Сжатие делает прокси, и ему явно указан порядок кодировок: сначала brotli, потом gzip. Порядок нужно задавать руками — типовая очередь в Traefik ставит gzip первым, и именно поэтому он и выбирал худшее, имея brotli под рукой.
Результат на живом сайте:
| Клиент | Было | Стало |
|---|---|---|
| Chrome (просит всё) | 169,7 КБ | 76,2 КБ |
| клиент без brotli | 169,7 КБ | 120,8 КБ |
Минус 55% на каждой загрузке главной, без единого изменения в содержимом страницы.
Ловушка, на которой легко потерять не свой сайт. Панели управления контейнерами часто раздают всем приложениям одинаковый, общий по имени набор правил сжатия. Пространство имён на прокси общее. Это значит, что «просто добавлю brotli к существующему правилу» меняет поведение не одного сайта, а всех, кто это имя использует — и два разных определения одного имени дают недетерминированный результат. Правило создаётся под собственным именем и цепляется к собственному маршруту. Другого безопасного способа нет.
Вторая половина: вес лежит не в разметке
Пока искали, куда делся brotli, нашли ещё одно. Вопрос «что именно весит в странице» имеет неожиданный ответ для любого современного фронтенда.
Разбор 16 августа 2026: в сжатой странице разметка — 37 КБ, а сериализованные данные для компонентов — 107 КБ. То есть три четверти веса — это не то, что вы видите в коде страницы, а то, что фреймворк везёт браузеру, чтобы «оживить» интерактивные блоки.
Заодно измерялось то, что обычно пугает разработчиков: 130 встроенных SVG-иконок стоили после сжатия 4 КБ. Сжатие прекрасно жмёт повторы, поэтому «много одинаковых иконок» — не проблема, хотя интуиция говорит обратное.
А в данных лежало то, чего там быть не должно: полные объекты переводов. На украинской главной — 18 штук с английскими и русскими ветками внутри, на странице портфолио — 62. Причина архитектурная: блоки накладывали перевод уже в браузере, поэтому сервер был обязан везти все языки каждому посетителю.
Перенесли наложение перевода на сервер. Стало:
| Страница | Было | Стало |
|---|---|---|
| портфолио | 216 КБ | 138 КБ |
| главная | 201 КБ | 160 КБ |
| английская главная | 189 КБ | 151 КБ |
Как посмотреть это у себя
Три проверки, каждая на несколько минут.
1. Что реально получает браузер. Заголовок как у Chrome, смотрим content-encoding и размер — команда в начале статьи. Если приехал gzip, а прокси настроен на brotli, ищите, кто сжал раньше.
2. Не проигрывает ли ваш сервер простому архиватору.
curl -s https://ваш-сайт.com/ > page.html
gzip -9 -c page.html | wc -c
Сравните с тем, что отдал сервер. Если сервер тяжелее — сжатие потоковое или уровень выставлен слишком низко.
3. Сколько из веса — это данные, а не разметка. В DevTools вкладка Network, фильтр Doc, смотрите размер документа. Дальше в коде страницы ищете большие блоки с данными, которые фреймворк вставляет для гидратации. Если их в разы больше видимой разметки — оптимизировать нужно их, а не картинки.
Отдельное, что стоит поискать в этих данных: не едет ли туда всё, что нужно лишь части посетителей — все языки, полные справочники, служебные поля из базы. Это самая частая и самая дешёвая находка.
Честные границы
Минус 90 КБ на загрузке — это ощутимо на мобильном интернете и почти незаметно на проводном. Сжатие не лечит медленный сервер: если время до первого байта у вас 800 миллисекунд, вес страницы — не главная ваша проблема, и начинать надо с другого конца.
Это также не влияет на позиции напрямую. Влияние косвенное и честно описано в документации Google: скорость входит в показатели удобства страницы, которые работают как один из факторов среди многих, а не как рычаг. Мы правили это не ради поиска, а потому что отдавать вдвое более тяжёлую страницу, имея настроенный brotli, — просто напрасная трата.
И главный вывод, который переносится на любой сайт: проверка, сделанная удобным для сервера способом, показывает состояние сервера, а не состояние посетителя. Заголовок, с которым вы замеряете, должен совпадать с тем, который шлёт браузер. Иначе всё прекрасно — ровно до первого настоящего пользователя.


