Быстродействие сайтаВеб-разработка

Пассажиры каждой страницы: словарь целого языка, вторая шапка и чат, которого не просили

5 сентября 2026 мы разобрали ответ собственного сайта строка за строкой и нашли пять вещей, которые ехали в браузер каждому посетителю, хотя ими никто не пользовался. 13 сентября нашлась шестая. Показываем байты до и после, урок о символах против байтов и пять проверок для своего сайта.

17 сентября 2026 г.
8 мин чтения

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

Вопрос этой статьи другой: что именно едет в браузер вместе с каждой страницей, хотя посетитель этим никогда не воспользуется. 5 сентября 2026 мы разобрали ответ собственного сайта и нашли пять таких пассажиров. 13 сентября нашелся шестой. 16 и 17 сентября проверили, что из этого осталось, — и увидели, что один пассажир уже понемногу возвращается.

Что нашли 5 сентября

В коммитах того дня записано: на страницу приходилось 300–380 КБ данных React, и самые крупные куски не имели отношения к самой странице.

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

Вторая шапка. Фреймворк кладет в каждый ответ заготовку страницы 404 — на случай, если адрес не найдется во время перехода. Наша страница 404 рисовала полную шапку с меню услуг, так что на каждую страницу ложились еще 18 КБ, которых никто никогда не видел.

Текст статьи трижды. Оглавление статьи собирали два компонента в браузере, и каждый получал весь HTML статьи, чтобы найти в нем заголовки. Текст приезжал один раз для чтения и еще дважды ради списка из нескольких пунктов.

Мобильное меню на компьютере. Содержимое мобильного меню — кнопки направлений, категории, поиск, 29 иконок — занимало 17 КБ разметки и около 150 узлов DOM. Сервер рисовал его на каждой странице и прятал прозрачностью, в том числе тем, кто открыл сайт с компьютера, где это меню не показывается вообще.

Обложка, о которой браузер узнавал поздно. Один прогон трассировки статьи на мобильном вьюпорте (Slow 4G, процессор замедлен в четыре раза) дал самый крупный элемент первого экрана за 1 094 мс. Из них 184 мс браузер просто не знал об обложке: она была фоном в стилях и обнаруживалась лишь после того, как стили загрузились. Еще 574 мс уходило на оригинальный JPEG 1200×630 весом 44–85 КБ, без всякого преобразования под экран.

Шестой пассажир, 13 сентября. Скрипт нашего чата — 57 КБ плюс настройки и открытое соединение — вставлялся сам при первом взаимодействии со страницей или когда она просто стояла. На практике его получал каждый посетитель, а не тот, кто нажал на чат.

Почему этого никто не заметил

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

Вторая причина — способ, которым это накапливается. Никто не решал везти словарь целого языка: его подключили один раз на весь сайт, когда словарь был маленьким, и дальше он рос вместе с сайтом. Заготовку 404 ставит фреймворк, а шапку в нее положили, потому что так выглядит обычная страница сайта. Каждое решение по отдельности разумно, а вместе получается багаж.

Что изменили

  • В браузер едут только те 19 разделов словаря, которые читают его компоненты. Перечень сверяет отдельный скрипт: он идет по графу импортов от файлов с 'use client' и падает, если раздела не хватает. Без такой проверки пропущенный раздел виден только на живом сайте — ключом перевода вместо текста.
  • Страница 404 берет легкую шапку без меню.
  • Пункты оглавления статьи собирает сервер, в пропсы идет короткий массив заголовков.
  • Содержимое мобильного меню монтируется после первого открытия. В серверной разметке статьи осталось 2 узла вместо 156, а ссылки для поисковых роботов стоят в панели меню для ПК, которая в HTML осталась.
  • Обложка стала обычным изображением с предварительной загрузкой и форматами под ширину экрана.
  • Чат загружается после клика по кнопке.

Что видим на живом сайте

16 сентября мы сняли три страницы прода с заголовком Accept-Encoding, как в Chrome, и разобрали их одним скриптом.

Страница HTML без сжатия Передано по сети Доля скриптов с данными React
главная 935 639 Б 83 209 Б 49%
статья блога 453 910 Б 59 273 Б 65%
страница услуги 633 694 Б 66 207 Б 61%

Шапка внутри заготовки 404 занимает теперь 137 байтов с пустым перечнем услуг — против 23 707 байтов настоящего меню на той же странице. Контейнер мобильного меню в разметке статьи пуст. Скрипт чата в коде страницы не упоминается вообще: вместо него кнопка на 707 байтов. Сам скрипт 17 сентября весил 56 953 байта, по сети сжатым 20 214, — но получает его лишь тот, кто нажал.

А вот словарь вернулся к прежнему размеру, и здесь есть отдельный урок.

Урок о единицах измерения

5 сентября в коммите записано «64 КБ». Когда 16-го мы пересчитали тот же файл словаря, вышло 63 261 символ — и 96 372 байта. Кириллица в UTF-8 занимает два байта на букву, так что записанная тогда цифра описывала символы, а не то, что действительно едет по сети.

В байтах картина такая. Полный словарь украинского на 5 сентября — 96 372 Б в 40 разделах. Девятнадцать нужных разделов после исправления — 57 976 Б. Те же девятнадцать разделов в текущей ветке — 67 924 Б. За одиннадцать дней словарь вырос, потому что на главной появились новые блоки: раздел Home увеличился с 12 852 до 20 539 байтов, 39 новых ключей, самый крупный из них — блок вопросов и ответов на 4 339 байтов.

Этот раздел приезжает на каждую страницу, потому что его читают компоненты главной. В ответе страницы статьи мы проверили все 53 строки из него длиннее 40 символов: ни одна не встречается больше нигде в этом ответе. То есть читатель статьи получает 20,5 КБ текстов главной, которых на его экране нет. После brotli это 5 553 байта против 16 510 на все девятнадцать разделов; числа считали для каждого куска отдельно, в составе страницы они будут немного другими.

Как проверить это у себя

1. Сколько данных везет страница. Для сайтов на Next.js с App Router откройте страницу, консоль DevTools и выполните:

const d = self.__next_f.map(x => x[1] || '').join('');
new TextEncoder().encode(d).length

Это байты. d.length даст символы, и на кириллическом сайте вы недосчитаетесь примерно трети — ровно так, как мы 5 сентября. На Next.js с Pages Router (без App Router) ищите блок <script id="__NEXT_DATA__"> вместо self.__next_f. В других фреймворках ищите в коде страницы крупные блоки <script type="application/json">, которые фреймворк вставляет для гидратации.

2. Не едет ли чужой текст. Скопируйте предложение, которое есть только на главной, и поищите его в коде страницы статьи или товара (Ctrl+U, затем Ctrl+F). Если оно там есть, а на экране нет, это пассажир. Так же ищите тексты попапов, полные списки городов, справочники, переводы других языков.

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

4. Что загружается до клика. Вкладка Network, перезагрузите страницу, немного пролистайте и ничего не нажимайте. Скрипты чатов, видеоплееров и карт, появившиеся в списке, получает каждый посетитель.

5. Чем является самый крупный элемент первого экрана. Во вкладке Performance найдите LCP. Если это картинка, заданная через background-image в стилях, браузер узнает о ней поздно — именно на этом мы потеряли 184 мс.

Что это не исправило

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

Шапка с деревом меню услуг по-прежнему занимает 23 707 байтов в данных каждой страницы. Это меню настоящее, им пользуются, и убирать его нет оснований.

Время появления обложки после изменения мы отдельно не замеряли, поэтому цифры «после» здесь не будет. Известно лишь, что теперь браузер узнает о ней с самого начала документа, со строки предварительной загрузки. Да и цифры «до» — 1 094 мс и 184 мс — это один запуск трассировки 5 сентября, а не медиана нескольких прогонов: на искусственно замедленных сети и процессоре такой замер гуляет от раза к разу.

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

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

Теги

PerformanceSEO

🤔Вам понравилась статья?

Ваше мнение помогает нам создавать лучший контент

Поделитесь с друзьями

Нашли что-нибудь полезное? 🚀

Помогите другим узнать это — поделитесь статьей в социальных сетях

https://lionex.com.ua/blog/pasazhyry-kozhnoi-storinky

💚 Спасибо, что помогаете нам расти

Владислав Чистяков

Пишет о том, что делает руками: интернет-магазины на OpenCart, приложения на Next.js, интеграции и скорость сайтов. В статьях — замеры и проверки, которые читатель может повторить на своём проекте, а не общие советы. Коммерческая разработка с 2015 года.

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

Ответы на популярные вопросы по теме

Современные фреймворки отдают не только готовый HTML, но и сериализованное описание страницы — чтобы браузер смог «оживить» интерактивные блоки без повторного запроса. Эти данные лежат в том же ответе, в крупных служебных скриптах. На наших трех страницах 16 сентября 2026 они занимали 49% несжатого HTML главной, 65% страницы статьи и 61% страницы услуги. Именно в них и прячутся вещи, которых посетитель никогда не увидит.

Откройте нужную страницу и консоль DevTools. На Next.js с App Router подойдет однострочный замер: собрать содержимое всех служебных блоков и измерить его через TextEncoder — это даст байты. Длина строки в символах на кириллическом сайте занижает результат примерно на треть, потому что кириллица в UTF-8 занимает два байта на букву. Мы сами на этом споткнулись: записанные 5 сентября «64 КБ» оказались 63 261 символом и 96 372 байтами.

В нашем случае нет, и причина конкретная: те же ссылки стоят в панели меню для компьютера, которая в HTML осталась. Робот видит их там. А если убрать скрытое меню, не оставив ссылок больше нигде, потеря будет настоящей. Перед таким изменением стоит сверить набор ссылок до и после — мы сверяли, и в серверной разметке статьи осталось 2 узла вместо 156 без потери ни одного адреса.

До 13 сентября 2026 скрипт нашего чата вставлялся сам при первом взаимодействии со страницей или когда она просто стояла, то есть его получал практически каждый посетитель. Теперь на странице живет кнопка на 707 байтов, а сам скрипт (17 сентября — 56 953 байта, по сети сжатым 20 214) приходит лишь тому, кто нажал. Цена осознанная: автоматическое открытие чата через 25 секунд или на намерение уйти со страницы больше не работает, потому что до клика движка чата на странице нет.

Они весят на медленном мобильном интернете и на слабых телефонах, где данные нужно не только загрузить, но и разобрать. На быстром соединении разница почти незаметна. Отдельно стоит смотреть на самый крупный элемент первого экрана: в нашей трассировке статьи (Slow 4G, процессор замедлен в четыре раза) он появлялся за 1 094 мс, и 184 мс из них браузер просто не знал об обложке, потому что она была фоном в стилях. Это уже ощутимо.

Получайте лучшие статьи на почту

Подпишитесь на нашу рассылку и получайте полезные советы, инсайты и новости о веб-разработке, маркетинге и бизнесе.

Мы уважаем вашу конфиденциальность. Отписаться можно в любой момент.

Похожие статьи

Все статьи
Сертификаты продлеваются сами: TLS на 116 сайтах и один, который не продлился
Веб-разработка

Сертификаты продлеваются сами: TLS на 116 сайтах и один, который не продлился

22 сентября 2026 года мы проверили HTTPS-сертификаты на 116 сайтах, которые уже измеряли для рыночных исследований, и для 104 из них сравнили состояние с августовским. Все 116 прошли проверку, 108 стоят на 89- и 90-дневных бесплатных сертификатах, и только у одного сайта сертификат до сих пор не продлился, хотя при типичных настройках уже должен был. Разбираем замеры, границы метода и показываем, как проверить свой сайт одной командой.

9 мин
22 сент.
Читать дальше
Healthcheck дал 60 % запросов приложения: что показали первые сутки метрик
Веб-разработка

Healthcheck дал 60 % запросов приложения: что показали первые сутки метрик

21 сентября 2026 года, в первые сутки учёта запросов по маршрутам, служебный /api/health получил 13 666 запросов — 60 % трафика приложения, и каждый шёл в общую базу. Рассказываем, какие две настройки это убрали, какую цену мы за них платим и как проверить свой healthcheck.

9 мин
22 сент.
Читать дальше
154 ошибки типов, которые выбрасывала сборка: что в них нашлось
Веб-разработка

154 ошибки типов, которые выбрасывала сборка: что в них нашлось

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

9 мин
22 сент.
Читать дальше