32 / 41
Что такое HTTP/2 Server Push?
Полный ответ
Как Server Push работает:
JavaScript
Без Server Push: С Server Push:
Браузер Сервер Браузер Сервер
| | | |
| -- GET / ------> | | -- GET / ------> |
| <-- HTML ------- | | <-- HTML ------- |
| | |<-- PUSH style.css (без запроса!)
| [парсит HTML] | |<-- PUSH app.js (без запроса!)
| | | |
| -- GET style.css-> | | [парсит HTML] |
| <-- style.css -- | | [CSS и JS уже получены]
| -- GET app.js --> | | |
| <-- app.js ----- | | |
Настройка на nginx (исторически):
Nginx
# nginx.conf (требует ngx_http_v2_module)
server {
listen 443 ssl http2;
location = / {
http2_push /css/style.css;
http2_push /js/app.js;
http2_push /img/logo.webp;
}
}
JavaScript
// Node.js с http2 модулем
import http2 from 'node:http2';
import fs from 'node:fs';
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
});
server.on('stream', (stream, headers) => {
if (headers[':path'] === '/') {
// Push CSS до отправки HTML
stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => {
if (err) return;
pushStream.respond({ 'content-type': 'text/css', ':status': 200 });
pushStream.end(fs.readFileSync('public/style.css'));
});
// Отправляем HTML
stream.respond({ 'content-type': 'text/html', ':status': 200 });
stream.end(fs.readFileSync('public/index.html'));
}
});
Почему Server Push провалился:
JavaScript
Проблема 1: Не знает о кеше браузера
Сервер пушит style.css каждый раз
Даже если у браузера уже есть свежая копия в кеше
Результат: трата трафика и bandwidth
Проблема 2: Приоритизация
Push-ресурсы конкурируют с основным HTML за bandwidth
Если запушить слишком много, HTML придёт медленнее
Парадокс: пытаемся ускорить, а замедляем
Проблема 3: Сложность конфигурации
Нужно точно знать, какие ресурсы понадобятся
Динамические страницы усложняют это многократно
Ошибки в конфигурации ухудшают производительность
Современные альтернативы:
HTML
<!-- Альтернатива 1: preload -- браузер запрашивает сам, но с приоритетом -->
<link rel="preload" href="/css/style.css" as="style">
<link rel="preload" href="/js/app.js" as="script">
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
JavaScript
Альтернатива 2: 103 Early Hints
Браузер Сервер
| |
| -- GET / --------------> |
| <-- 103 Early Hints ---- | (мгновенно, пока сервер готовит HTML)
| Link: </style.css>; rel=preload
| Link: </app.js>; rel=preload
| |
| [браузер уже грузит |
| style.css и app.js] | [сервер готовит HTML]
| |
| <-- 200 OK + HTML ------ |
| [CSS и JS уже загружены или почти]
Nginx
# nginx с 103 Early Hints
location = / {
add_header Link "</css/style.css>; rel=preload; as=style" early;
add_header Link "</js/app.js>; rel=preload; as=script" early;
proxy_pass http://backend;
}
📌 Реальные кейсы
Почему Chrome убрал Server Push:
JavaScript
Данные Chrome (2022):
-- Менее 1.25% HTTP/2 страниц использовали Server Push
-- В большинстве случаев Push ухудшал или не влиял на метрики
-- 103 Early Hints покрывает те же сценарии без проблем с кешем
-- Поддержка Server Push удалена из Chrome начиная с версии 106
Когда Server Push имел смысл (исторически):
JavaScript
-- Первый визит пользователя (пустой кеш)
-- Известный набор критических ресурсов
-- Медленный бэкенд (пока сервер думает, можно пушить статику)
Сейчас все эти случаи покрываются 103 Early Hints лучше
Резюме
Server Push был многообещающей фичей HTTP/2, но на практике не оправдал ожиданий из-за проблем с кешированием и приоритизацией. Chrome удалил его поддержку. Современные альтернативы: <link rel="preload"> для контроля из HTML и 103 Early Hints для серверной подсказки. Не стоит тратить время на настройку Server Push в новых проектах.