Виртуальный хостинг давно перестал быть «медленным по умолчанию». На современных площадках виртуальный хостинг даёт PHP 8.x, OPcache, HTTP/2 и Brotli. Задача администратора — включить нужные опции, правильно настроить кэш и заголовки, подтянуть фронтенд и измерить результат. Ниже — концентрат практики для тех, кто отвечает за RPS, TTFB и стабильность на общем хостинге.
Обновляемся на PHP 8.x и убираем «узкие места»
Переход на PHP 8.1–8.3 почти всегда даёт мгновенный прирост производительности: быстрее ядро, улучшены строки/массивы, JIT. Важно подготовиться: проверить совместимость кода/расширений, отключить отладчики и оптимизировать автозагрузку.
- Создайте тестовый стенд или поддомен и переключите его на PHP 8.x через панель хостинга. Для продвинутого стенда на отдельном окружении смотрите материал по стендированию WP на VDS: руководство.
- Прогоните тесты и базовые сценарии. Для CMS — ключевые страницы, корзина/заказ, кабинет.
- Если используете Composer — обновите зависимости и оптимизируйте автозагрузчик:
composer install --no-dev --optimize-autoloader
. - Выключите Xdebug в продакшене — он многократно замедляет обработку запросов.
- Логи — в файл, а не на экран:
display_errors=0
,log_errors=1
.
На виртуальном хостинге вы не управляете системным php.ini, но почти всегда доступен пользовательский .user.ini
или локальный php.ini в корне сайта. Через него и включаем OPcache/настройки.
OPcache: обязательный ускоритель для PHP
OPcache компилирует PHP-скрипты в байткод и хранит его в памяти. Это резко снижает CPU-нагрузку и TTFB для динамики. На общем хостинге его можно включить через .user.ini
(или аналог в панели):
; .user.ini (или локальный php.ini)
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.fast_shutdown=1
; JIT может не дать профита типичным веб-нагрузкам
opcache.jit=tracing
opcache.jit_buffer_size=64M
Пояснения к ключевым параметрам:
opcache.memory_consumption
— объём памяти под байткод. Для средних проектов 128–192 МБ, крупным — 256+.opcache.max_accelerated_files
— индексы для кэшируемых файлов. Ориентируйтесь на число PHP-файлов в проекте (10–50 тыс.).validate_timestamps
иrevalidate_freq
— как часто OPcache проверяет обновления. В продакшене обычно 30–60 с, чтобы не грузить FS.- JIT полезен редко (CPU-интенсивные задачи). Сравните метрики до/после.
Если деплои частые — оставляйте validate_timestamps=1
. В CD/релиз-скриптах можно применять opcache_reset()
(если разрешено хостингом).
APCu и объектный кэш
На ряде тарифов доступен APCu — локальный in-memory кэш «ключ–значение», быстрее файлового и шарится между процессами одного пользователя. Если модуль есть — используйте его для кэширования частых вычислений и небольших структур. Redis/Memcached обычно недоступны на shared; они потребуют отдельного окружения на VDS.
Файловый кэш остаётся универсальным вариантом — следите за количеством мелких файлов и TTL, чтобы не упереться в I/O. Для CMS — используйте штатные адаптеры/плагины.
Кэш на уровне приложения: CMS и фреймворки
Почти все популярные CMS/фреймворки имеют страничный и объектный кэш. Выберите один основной слой и доведите его до стабильности — «три кэша поверх» часто дают обратный эффект.
WordPress:
- Включите страницный кэш (
define('WP_CACHE', true);
) и поставьте плагин кэширования (страничный + минификация + объединение). Для динамики настройте пропуски по куки/URL. - Отключите псевдокрон:
define('DISABLE_WP_CRON', true);
и вызывайте реальный cron (запрос кwp-cron.php
) по расписанию. - Проверьте
wp_options
на раздутые автозагружаемые опции (autoload='yes'
), почистите тяжёлые транзиенты.
Laravel:
- Соберите кэш конфигов/маршрутов/представлений:
php artisan config:cache
,route:cache
,view:cache
. - Поставьте
APP_ENV=production
,APP_DEBUG=false
, используйте оптимизированный автозагрузчик Composer. - Файловый или APCu-адаптер — для кэша/сессий, если Redis недоступен.
Drupal, Bitrix, Yii, Symfony — аналогично: включайте встроенный кэш, отключайте дебаг, разделяйте публичный/приватный кэш, следите за инвалидациями.

HTTP/2: мультиплексирование без спрайтов и «шардинга»
HTTP/2 даёт одновременную загрузку множества ресурсов в одном соединении и экономит RTT. На практике это означает: не нужно дробить ресурсы по поддоменам, делать спрайты и агрессивно инлайнить всё подряд — лучше держать разумное число файлов, включить кэширование и проставить приоритеты.
Как проверить, что сайт обслуживается HTTP/2:
curl -I -s --http2 https://example.com/ | head -n 5
В статусе увидите HTTP/2 200
. Если приходит HTTP/1.1 — проверьте включение TLS и совместимость. При необходимости подключите надёжные SSL-сертификаты. Если только планируете миграцию на HTTPS, пригодится разбор 301/HSTS: пошаговый гайд.
HTTP/2 Server Push признан спорной практикой — его заменили preload и 103 Early Hints. На общем хостинге чаще всего доступен Link: rel=preload
через .htaccess:
# .htaccess: минимальные прелоады критических ресурсов
<IfModule mod_headers.c>
Header add Link "</assets/app.css>; rel=preload; as=style"
Header add Link "</assets/app.js>; rel=preload; as=script"
</IfModule>
Brotli и Gzip: сжимаем корректно
Brotli (br) обычно даёт 10–20% выигрыша к размеру по сравнению с Gzip. На виртуальном хостинге Brotli часто включается в панели, но можно подстраховаться через .htaccess.
# .htaccess — включаем Brotli, с Gzip как фолбэк
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml
BrotliCompressionQuality 5
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml
</IfModule>
Проверка сжатия:
curl -sI -H "Accept-Encoding: br" https://example.com/ | grep -i content-encoding
# Должно быть: content-encoding: br
Не сжимайте уже сжатые форматы (JPEG/PNG/WebP/AVIF, PDF) и архивы.
Кэш статических ресурсов: Cache-Control и Expires
Максимум по фронтенду даёт длинный TTL для неизменяемых ассетов (CSS/JS/шрифты/изображения) и версионирование файлов (хеш в имени). Браузер хранит файл год, вы обновляете URL при релизе.
# .htaccess — долгий кэш для ассетов
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/avif "access plus 1 year"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(css|js|woff2|svg|webp|avif)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
<FilesMatch "\.(html|php)$">
Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
</FilesMatch>
</IfModule>
Убедитесь, что сборщик (Webpack/Vite/Gulp) добавляет контент-хеш в имена файлов. Query string версии хуже — некоторые прокси их игнорируют.
Изображения и шрифты: экономим килобайты
Переводите ключевые изображения в WebP/AVIF с фолбэком для старых браузеров. Прописывайте srcset
и размеры, чтобы мобильные не тянули десктопные версии. Для шрифтов используйте woff2
, font-display: swap
и предзагрузку критичных начертаний.
# .htaccess — корректные типы для современных форматов
AddType image/avif .avif
AddType image/webp .webp
AddType font/woff2 .woff2
Добавляйте preload
для самых важных шрифтов и CSS умеренно — перегруз прелоадами мешает приоритизации HTTP/2.
CDN и edge-кеширование
CDN разгружает бэкенд и сокращает задержки до пользователей. Даже на виртуальном хостинге можно вынести на CDN статику, а иногда — и HTML при аккуратных правилах.
- Отдавайте с длинным TTL всё неизменяемое. Для HTML — короткий TTL или умные правила обхода кэша по куки/URL (страницы с авторизацией не кэшируйте).
- Включите Brotli и HTTP/2 (или HTTP/3, если доступно) на периметре CDN.
- Версионируйте файлы и не очищайте весь кэш при каждом релизе.
При включении CDN проверьте CORS для шрифтов/шаблонов и заголовки Cache-Control
— большинство CDN уважают их по умолчанию.
База данных: ускоряем без доступа к MySQL-конфигу
На shared вы не тюните сервер БД, но можете сильно повлиять на запросы.
- Избегайте
SELECT *
— выбирайте только нужные поля. - Добавляйте недостающие индексы для частых фильтров и джоинов (на бэкапе/стенде).
- Сокращайте число запросов на горячих страницах: кэшируйте фрагменты и результаты.
- Отслеживайте медленные запросы средствами фреймворка/профайлера и правьте их в коде.
Подключения по PDO/MySQLi держите краткими; используйте переиспользование на стороне PHP-FPM, если позволяет SAPI на хостинге. Постоянные соединения (persistent
) не всегда доступны и могут вредить при неверной конфигурации.
Микрооптимизации PHP-кода
Несколько действенных шагов:
- Уберите лишние
require_once
и медленные автолоадеры — переходите на Composer c оптимизацией классов. - Не стартуйте сессию там, где она не нужна — это лишние файлы/локи.
- Кэшируйте результаты тяжёлых регулярных выражений и сериализаций.
- Минимизируйте
file_exists
/is_file
в горячих путях — OPcache и так отслеживает файлы.
План кэш-инвалидаций и прогрев
Хаотичный сброс кэшей под нагрузкой — частая причина «пилы» и 5xx. Сформируйте явный план:
- Прогревайте топовые страницы после деплоя/очистки: скрипт на curl/wget по списку URL.
- Очищайте кэш точечно — по тегам/ключам, а не «всё и сразу».
- Разносите очистку и пик трафика по времени, используйте крон.
# простой прогрев (bash)
while read -r url; do
curl -s -o /dev/null -H "Accept-Encoding: br" "$url" &
done <<EOF
https://example.com/
https://example.com/catalog/
https://example.com/blog/
EOF
wait
Измеряем: до и после
Оптимизации должны подтверждаться цифрами. Минимальный набор:
- TTFB и время до полной загрузки ключевых страниц.
- Количество и медленные запросы к БД.
- Хиты/промахи кэша (приложение/CDN).
- Размеры бандлов и сжатие (br/gzip) по типам контента.
Инструменты: DevTools, Lighthouse, WebPageTest, curl
для заголовков/протоколов, хвосты access/error. Фиксируйте «до/после» каждой правки — так быстрее поймёте, что реально работает.
Чек-лист внедрения
- Переключите сайт на PHP 8.2/8.3, проверьте совместимость на стенде.
- Включите OPcache и задайте параметры под размер проекта (
.user.ini
). - Оптимизируйте автозагрузчик Composer, отключите дебаг/отладчики.
- Включите страничный/объектный кэш в CMS/фреймворке, настройте инвалидации.
- Проверьте HTTP/2, включите Brotli (или Gzip) и длинные TTL для статики.
- Версионируйте ассеты, добавьте
preload
для критичных ресурсов, шрифты сfont-display: swap
. - Подключите CDN для статики, проверьте заголовки и CORS.
- Сократите и проиндексируйте «тяжёлые» запросы к БД, почистите автозагружаемые опции.
- Настройте крон для прогрева кэша и фоновых задач.
- Замерьте метрики и закрепите удачные практики в релиз-процессе.
Разбор частых проблем
- TTFB «пилит», всплески CPU — проверьте, не сбрасывается ли кэш на каждом деплое/логине, не включён ли Xdebug, хватает ли памяти OPcache.
- Статика быстрая, а HTML рендерится долго — индексируйте горячие запросы, включите фрагментный кэш, сократите вызовы сторонних API в рендере.
- Браузер не получает Brotli — проверьте
Accept-Encoding
клиента, наличиеmod_brotli
и конфликты в .htaccess. - Статика не кэшируется — проверьте
Cache-Control
/Expires
и отсутствиеno-store
от приложения.
Итог
Виртуальный хостинг позволяет добиться впечатляющей скорости, если последовательно включить PHP 8.x, грамотно настроить OPcache, кэш приложения, заголовки и сжатие, а также использовать HTTP/2/Brotli и CDN. На выходе — более низкий TTFB, стабильный отклик под нагрузкой и экономия ресурсов. Если нужна тонкая системная настройка и собственные сервисы — время посмотреть в сторону VDS.