HTTP/2 и сжатие могут сократить передачу ресурсов и помочь загрузке, в том числе LCP. Сами по себе они не устраняют сдвиги макета и не гарантируют роста позиций в поиске. Отдельно измеряйте передачу данных, отрисовку и поведение страницы.
HTTP/2, HTTPS и размещение приложения
HTTP/2 передаёт несколько потоков запросов по одному соединению, уменьшая блокировку на уровне HTTP/1.1. При этом он использует TCP: потеря пакета может задержать все потоки на транспортном уровне. HTTP/3 уже применяется и иначе организует транспорт. Выбирайте протокол по измерениям и возможностям размещения.
Браузеры используют HTTP/2 через TLS. На управляемом хостинге, например Vercel, проверяйте протокол соединения с пограничным сервером. При самостоятельном размещении TLS и HTTP/2 можно завершать на обратном прокси или CDN перед сервером Next.js. Обычный Node.js-сервер с модулем https не становится HTTP/2-сервером только из-за HTTPS.
Для локального эксперимента с HTTPS можно создать сертификат для localhost. Это не сертификат для production:
openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost'
Следующий пример показывает HTTPS с HTTP/1.1, а не развёртывание HTTP/2. Нужен существующий проект Next.js, а в production-режиме — готовая сборка. Если особых требований нет, используйте стандартный сервер Next.js за прокси.
import next from 'next'
import fs from 'node:fs'
import https from 'node:https'
const app = next({ dev: process.env.NODE_ENV !== 'production', port: 3000 })
const handle = app.getRequestHandler()
async function startServer() {
await app.prepare()
https
.createServer(
{
cert: fs.readFileSync('./cert.pem'),
key: fs.readFileSync('./key.pem'),
},
async (request, response) => {
await handle(request, response)
},
)
.listen(3000)
console.info(`Ready on https://localhost:3000`)
}
startServer()
Проверьте фактический протокол и сжатие
Посмотрите столбец Protocol на вкладке Network в Chrome DevTools. В сборке curl с поддержкой HTTP/2 первая команда выведет фактически выбранную версию: запрос HTTP/2 допускает откат на другой протокол. Вторая команда проверяет заголовки GET-ответа с заявленной поддержкой Brotli и gzip.
curl --http2 -sS -o /dev/null -w '%{http_version}\n' https://your-site.com
curl -sS -D - -o /dev/null -H 'Accept-Encoding: br, gzip' https://your-site.com
Brotli и gzip
При запуске через next start Next.js по умолчанию использует gzip. Brotli может сильнее сжать текст, но результат зависит от данных и настроек: универсального выигрыша 20–25% нет. На управляемом хостинге проверяйте реальные ответы. При самостоятельном размещении настройте Brotli на поддерживающем его прокси или CDN.
Отключайте сжатие Next.js только после настройки сжатия на другом уровне. Иначе сохраните значение по умолчанию. Эта настройка передаёт ответственность другому серверу, а не включает Brotli:
// next.config.mjs
export default {
compress: false,
}
Пример заголовков ответа, сжатого Brotli:
Content-Encoding: br
Vary: Accept-Encoding
Не выставляйте Content-Encoding вручную для несжатого тела. Проверьте сжатый и резервный варианты ответа, а также учёт Accept-Encoding в кеше.
Числа ниже — учебный пример, а не измерение или гарантированный коэффициент сжатия:
| Формат | Исходный JavaScript | Сжатый размер в примере |
|---|---|---|
| Gzip | 100 KB | 30 KB |
| Brotli | 100 KB | 22 KB |
Предзагрузка и Server Push — разные механизмы
Компонент Link в Next.js может заранее загружать ресурсы маршрута. Это запрос браузера, а не HTTP/2 Server Push. Начиная с Chrome 106 поддержка Server Push отключена по умолчанию; не делайте современную оптимизацию зависимой от неё.
import Link from 'next/link'
export default function AboutLink() {
return <Link href="/about" prefetch>About</Link>
}
Для действительно критичного шрифта может подойти preload. Замените путь на реальный ресурс и согласуйте тип и настройки cross-origin:
<link rel="preload" href="/fonts/site.woff2" as="font" type="font/woff2" crossorigin>
Prefetch и preload расходуют пропускную способность. Универсального ограничения в пять или шесть ресурсов нет: добавляйте подсказки там, где измерения подтверждают пользу для загрузки или перехода.
Оптимизация изображений
next/image может отдавать оптимизированные форматы с учётом настроек и заголовка Accept браузера. Формат по умолчанию — WebP; для AVIF нужна соответствующая настройка. Указывайте размеры, чтобы резервировать место и уменьшать сдвиги макета.
import Image from 'next/image'
export default function ExampleImage() {
return <Image src="/example.jpg" alt="Example" width={800} height={600} quality={75} />
}
Размеры файлов ниже иллюстративны. Результат зависит от изображения, разрешения и качества. Проверяйте браузеры своей аудитории вместо фиксированных процентов поддержки.
| Формат | Пример для 1920 × 1080 | Проверка поддержки |
|---|---|---|
| JPEG | 200 KB | Целевые браузеры |
| WebP | 120 KB | Целевые браузеры |
| AVIF | 80 KB | Целевые браузеры |
Частые ошибки и сравнение результата
| Проблема | Что проверить |
|---|---|
| Нет действительного TLS-сертификата | Настройте доверенный сертификат для production, например через Let’s Encrypt. |
| Ожидали Brotli, но ответ без него | Проверьте заголовки запроса и ответа, тип содержимого и настройки прокси. |
| Слишком много ранних запросов | Уберите бесполезные prefetch/preload и повторите сравнение. |
Повторяйте измерения на той же странице с одинаковыми условиями устройства, сети и кеша. Speed Scanner и WebPageTest помогают сравнивать загрузку; само название протокола не доказывает улучшения. Сохраните настройки и результаты и повторяйте проверку после значимых изменений.
