Хостингу принадлежит одна цифра в отчёте о производительности сайта: время до первого байта, TTFB. Это ожидание между тем, как браузер запросил страницу, и тем, как пришёл первый байт ответа; оно складывается из DNS, установки соединения, расстояния между посетителем и машиной и времени, которое ваш сервер тратит на размышления. Всё, что идёт после первого байта - размер картинок, объём исполняемого JavaScript, прыгает ли вёрстка, - забота вашего сайта, и никакой купленный тариф этого не изменит.
Кажется, что доля небольшая, но это не так. TTFB - пол под Largest Contentful Paint: если сервер отвечает 1,5 секунды, даже идеальный фронтенд провалит порог в 2,5 секунды. Возьмите TTFB под контроль, и остальное станет решаемым. Игнорируйте его, и ничего из остального не хватит.
Три Core Web Vitals и где среди них TTFB#
Core Web Vitals - набор из трёх полевых метрик, которые измеряются на реальных визитах и сообщаются по 75-му процентилю за скользящие 28 дней. Пороги:
| Метрика | Что измеряет | Хорошо | Плохо |
|---|---|---|---|
| LCP | Время до отрисовки самого крупного элемента | 2,5 с или меньше | больше 4,0 с |
| INP | Отзывчивость на касания, клики и клавиши | 200 мс или меньше | больше 500 мс |
| CLS | Насколько смещается вёрстка при загрузке | 0,1 или меньше | больше 0,25 |
INP заменил First Input Delay в качестве Core Web Vital в марте 2024 года, и он строже: он смотрит на худшее взаимодействие на странице, а не только на первое, и измеряет время до отрисовки следующего кадра, а не только до начала работы обработчика.
TTFB не входит в эти три. Это диагностическая метрика, и рекомендация такова: 0,8 секунды или меньше для хорошей оценки, а всё, что больше 1,8 секунды, считается плохим. Он важен потому, что LCP раскладывается на четыре части, идущие по порядку: TTFB, задержка до того, как браузер обнаружит ресурс LCP, время загрузки этого ресурса и задержка до отрисовки. Первая целиком на стороне сервера, и она прямо вычитается из бюджета остальных трёх.
Про 75-й процентиль многие забывают. Ваше собственное быстрое соединение с прогретым кэшем ни при чём. У одного посетителя из четырёх опыт хуже той цифры, по которой вас оценивают, а хвост состоит из мобильных соединений, холодных кэшей и медленных устройств.
Чего ждёт первый байт#
Измеряйте каждую часть, а не гадайте. curl печатает всю разбивку:
$ curl -s -o /dev/null -w "dns: %{time_namelookup}s connect: %{time_connect}s \tls: %{time_appconnect}s ttfb: %{time_starttransfer}s total: %{time_total}s\n" \ https://example.com/Это накопленное время от начала запроса, так что стоимость каждого этапа - разница с предыдущим. Типичный здоровый результат с машины на том же континенте выглядит так: DNS меньше 30 мс, connect добавляет 20-40 мс, TLS - ещё 20-40 мс, а первый байт приходит через 30-150 мс после этого в зависимости от того, что пришлось делать серверу.
Измерение искажают две вещи. Запустите его дважды: второй запуск использует уже полученный ответ DNS и точнее показывает вернувшегося посетителя. И запускайте не из офиса, потому что ваша собственная задержка до сервера - не задержка ваших посетителей.
Для серверной части инструмент, превращающий догадку в число, - Server-Timing. Его выдаёт ваше приложение, а инструменты разработчика в браузере показывают:
Server-Timing: db;dur=53, render;dur=31, cache;desc="MISS"Добавьте его вокруг вызовов базы данных и рендера шаблона, задеплойте, и спор о том, медленна ли база или фреймворк, закончится в тот же день.
Что на самом деле меняет хостинг#
Четыре вещи, в порядке того, насколько они обычно важны.
Работа сервера. Время между получением запроса сервером и началом ответа. Для сайта на PHP это запуск PHP, загрузка фреймворка, запросы к базе и рендер шаблона. Именно здесь быстрый тариф действительно быстрее: больше доли CPU - меньше очередей, больше памяти - кэши остаются тёплыми. Здесь же и самые большие бесплатные выигрыши: OPcache, кэш объектов и исправление страницы, выполняющей 400 запросов.
Расстояние. Свет в оптоволокне проходит примерно 200 км за миллисекунду, а каждому запросу до первого байта нужно несколько круговых обменов. С сервера в Германии примерное время кругового обмена такое:
| Из Германии до | Примерный RTT |
|---|---|
| Западной Европы | 10-30 мс |
| Восточной Европы, Турции | 30-70 мс |
| Восточного побережья США | 85-110 мс |
| Западного побережья США, Индии | 130-180 мс |
| Бразилии | 180-220 мс |
| Австралии | 250-300 мс |
Умножьте на два-три круга, которые нужны свежему соединению HTTPS, и станет понятно, почему посетитель из Австралии отстаёт на секунду ещё до того, как запустится ваш код. Никакой тариф этого не исправит; поможет только кэш поближе к посетителю. Честная версия этого компромисса - как выбрать, где будет жить ваш сервер.
Установка соединения. HTTP/2 позволяет многим запросам делить одно соединение, так что рукопожатие оплачивается один раз, а не на каждый ресурс. TLS 1.3 завершается за один круг там, где 1.2 требовал двух. Keep-alive важен по той же причине. Это в основном значения по умолчанию вашего веб-сервера, и обычно они уже правильные.
Диск и память. Хранилище NVMe сокращает всё, что обращается к файловой системе: холодное чтение файла PHP, страницу базы данных, которой нет в памяти, большую загрузку. Заметнее всего это на базе данных, не помещающейся в RAM. Цифры - в статье что на самом деле меняет NVMe.
На RE:NODE всё это стоит на NVMe в пуле ZFS в Германии, а доля CPU в вашем тарифе - жёсткое ограничение, а не разрешение на всплески. Жёсткий лимит менее лестен в бенчмарке и намного предсказуемее в продакшене: сервер на 100% работает медленно, но его никогда не приостанавливают, а графики консоли показывают память, CPU и диск относительно лимитов, так что видно, в какой из них вы на самом деле упираетесь. Почему такое ограничение - честная модель, объясняет статья общий CPU и шумные соседи.
Чего хостинг изменить не может#
Будем так же ясны и здесь, потому что именно тут тратится большая часть денег на производительность.
- Вес изображений. Hero-картинка в 3 МБ - это 3 МБ с любого сервера. Элемент LCP на большинстве страниц - изображение, и решение - экспортировать его в размере отображения в WebP или AVIF.
- Исполнение JavaScript. INP решается на устройстве посетителя вашим основным потоком. Более быстрый сервер не сделает задачу в 400 мс короче.
- Смещение вёрстки. CLS вызывают изображения без размеров, реклама и встраиваемое содержимое, которое вставляется само, и шрифты, подменяющиеся на другой размер. Всегда чистый фронтенд.
- Сторонние теги. Аналитика, чат-виджеты, менеджеры согласия и пиксели загружаются с чужих серверов по чужому расписанию.
- Блокирующие отрисовку ресурсы. Таблица стилей в head блокирует отрисовку, пока не придёт, кто бы её ни хостил.
- Устройство и сеть посетителя. Пятилетний телефон в поезде - это и есть 75-й процентиль.
Практическая проверка перед повышением тарифа: посмотрите графики CPU и памяти в самый загруженный час. Если у вас 20% CPU и половина памяти, более крупный тариф ничего не изменит, а время до первого байта, которым вы недовольны, идёт от вашего кода, ваших запросов или расстояния. Тот же довод, но подробнее, - в статье когда пора переходить на другой тариф.
Как измерять правильно: поле и лаборатория#
Два вида данных, и они отвечают на разные вопросы.
Полевые данные приходят от реальных визитов. Публичный набор данных Chrome лежит в основе отчёта Core Web Vitals в Search Console и верхней половины PageSpeed Insights, агрегированный за 28 дней по 75-му процентилю. Именно им пользуется поиск, он охватывает вашу реальную аудиторию и устройства, и он медленно меняется: сегодняшнее исправление проявится в следующие недели.
Лабораторные данные приходят из синтетического прогона: Lighthouse, нижняя половина PageSpeed Insights, WebPageTest. Они воспроизводимы и мгновенны, что делает их подходящими для сравнения двух версий страницы, и они не могут нормально измерить INP, потому что никто не взаимодействует. Лабораторный прогон к тому же использует имитированное соединение, так что его LCP - не LCP ваших посетителей.
Если у сайта слишком мало трафика для полевых данных, собирайте свои собственные библиотекой web-vitals, которая отправляет те же метрики из реальных сессий на любой endpoint. Сто реальных визитов скажут больше, чем тысяча лабораторных прогонов.
Когда вы ищете именно серверную проблему, самый быстрый цикл - curl снаружи, в цикле, в тихий час и в загруженный. TTFB, который в порядке в 3 ночи и ужасен в 9 вечера, - проблема ёмкости. Постоянно плохой - проблема кода или запросов. Плохой только у некоторых страниц - отсутствующий индекс или медленный сторонний вызов на пути запроса.
Исправляем TTFB по порядку#
- Кэшируйте HTML. Страница, отданная из кэша, обходит фреймворк, базу данных и большую часть риска. Полностраничный кэш превращает динамический ответ в 600 мс в 20 мс. Для WordPress это плагин кэша страниц плюс кэш объектов; для фреймворка - кэш ответов или обратный прокси. Что отправлять вместе с ним, чтобы браузеры и CDN сотрудничали, описано в статье заголовки HTTP-кэширования простыми словами.
- Включите OPcache и не трогайте. PHP без OPcache перекомпилирует каждый файл на каждом запросе. С
opcache.enable=1и достаточнымopcache.memory_consumptionэта работа делается один раз. В продакшенеopcache.validate_timestamps=0убирает вызов stat на каждый файл ценой того, что при деплое нужен сброс. Остальное - в статье настройки php.ini, которые важны. - Считайте запросы. Самая частая причина TTFB в 900 мс - цикл, выполняющий один запрос на строку. Логируйте число запросов на страницу при разработке; всё, что больше примерно 30 на обычную страницу, требует объяснения.
- Уберите блокирующий сторонний вызов. Обращение к внешнему API внутри рендера страницы делает ваш TTFB зависимым от чужой доступности. Вынесите его в очередь, закэшируйте результат или примите риск осознанно.
- Уберите цепочки редиректов. Каждый переход - полный круговой обмен, а редирект на другое имя хоста снова добавляет DNS и TLS.
http://example.comнаhttps://example.comнаhttps://www.example.com- два избежимых ожидания при каждом первом визите. - Сжимайте и держите соединения тёплыми. gzip или brotli для текста, HTTP/2 включён, keep-alive включён. Обычно это значения по умолчанию, но проверьте, а не предполагайте.
- И только потом покупайте больше сервера. Если CPU упирается под трафиком или память на лимите, проблема в тарифе, а всё выше - перестановка мебели. Как рассчитать, что нужно, до самого дня, описано в статье подбор размера веб-приложения для дня запуска.
Исправляем LCP, когда TTFB хорош#
При быстром первом байте LCP определяется тем, как быстро браузер находит и рисует самый крупный элемент - почти всегда это картинка или большой блок текста.
- Не откладывайте загрузку изображения LCP.
loading="lazy"на hero-картинке задерживает именно то, что измеряется. Откладывайте только то, что ниже первого экрана. - Дайте ему приоритет.
fetchpriority="high"на изображении LCP говорит браузеру загружать его раньше других картинок, а ссылкаpreloadпомогает, когда изображение обнаруживается поздно, например из CSS. - Заранее подключайтесь к неизбежным origin.
rel="preconnect"к хосту шрифтов или изображений оплачивает DNS и TLS параллельно, а не последовательно. - Отдавайте шрифты со своего origin и с `font-display: swap`. Текст, невидимый, пока грузится шрифт, - это текст, который не отрисован.
- Задавайте `width` и `height` каждому изображению. Это самое большое исправление CLS, и оно ничего не стоит.
- Сократите блокирующий отрисовку CSS. Встройте то, что нужно первому экрану, и загружайте остальное асинхронно, если ваша сборка позволяет это без переписывания.
Статический сайт получает большую часть этого бесплатно, и это часть довода за то, чтобы строить такой, где контент позволяет, - см. хостинг статических сайтов. CMS получает это от слоя кэширования плюс дисциплины с плагинами; конкретная версия - скорость и кэширование WordPress.
FAQ#
Какой TTFB считается хорошим?
Менее 800 мс по 75-му процентилю - опубликованный порог хорошей оценки, но это потолок, а не цель. Кэшированная страница на близком сервере отвечает за 30-80 мс; динамическая страница, выполняющая настоящую работу, всё равно должна уложиться в 300 мс. Если вы за секундой, что-то не так, а не просто не оптимизировано.
Улучшит ли более дорогой тариф мои Core Web Vitals?
Только если вы ограничены ресурсами. Больше CPU и памяти сокращают часть TTFB, связанную с работой сервера, что помогает LCP. Для INP, CLS, веса изображений и сторонних скриптов они бесполезны, а именно оттуда берётся большинство проваленных оценок. Прежде чем тратить деньги, посмотрите графики использования.
Исправляет ли CDN TTFB?
Для кэшированных ответов - да, разительно, потому что ответ приходит с машины рядом с посетителем. Для всего, что CDN кэшировать не может - страница с входом, оформление заказа, вызов API, - запрос по-прежнему идёт до вашего origin и обратно, так что цифру по-прежнему определяют скорость origin и расстояние до него.
Является ли TTFB фактором ранжирования?
Не напрямую. LCP, INP и CLS входят в сигналы качества страницы, а TTFB входит в LCP. Относитесь к нему как к средству, а не к цели: причина исправлять его в том, что посетители уходят с медленных страниц, а этот эффект больше любой поправки в ранжировании.
Почему в Lighthouse у меня 100, а отчёт Search Console провален?
Потому что они измеряют разное. Lighthouse - один синтетический прогон на имитированном соединении из дата-центра. Search Console сообщает, что видели реальные посетители на реальных устройствах и в реальных сетях за последние 28 дней по 75-му процентилю. Доверяйте полевым данным, а лабораторный прогон используйте для сравнения изменений.
Через какое время после исправления отчёт улучшится?
Полевые данные - скользящее окно в 28 дней, поэтому изменению нужно несколько дней, чтобы показать движение, и около месяца, чтобы отразиться полностью. Проверяйте лабораторными инструментами и собственными измерениями на реальных пользователях сразу; официальный отчёт воспринимайте как подтверждение, а не как обратную связь.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.