Какие оптимизации возможны для сервер-сайт рендеринга
Что проверяют
Понимаете ли вы, из чего складывается время ответа при серверном рендеринге: получение данных, сам рендер, передача HTML и гидратация на клиенте. Ждут оптимизаций по этапам, а не общих слов про сжатие и CDN. Следом часто спрашивают про стриминг и ошибки гидратации.
Как отвечать
Разложите по этапам:
- не рендерить повторно: страницу, одинаковую для всех, отдавайте статикой (SSG) или с периодической перегенерацией (ISR в Next.js). Иначе кешируйте готовый HTML на CDN через
Cache-Control: s-maxage=60, stale-while-revalidate=300. Персональные куски грузите отдельно, чтобы одно имя пользователя не отменяло кеш; - данные: независимые запросы параллельно через
Promise.all, а не цепочкойawait, дедупликация одинаковых запросов в рамках рендера, кеш ответов API. Иначе TTFB складывается из водопада; - стриминг:
renderToPipeableStreamвместо синхронногоrenderToString, который блокирует event loop Node.js. СSuspenseоболочка страницы уходит сразу, медленные блоки дописываются по готовности; - меньше JS на клиенте: React Server Components не отправляют код компонентов в браузер, выборочная гидратация оживляет только интерактивные части. Сериализованное состояние в HTML тоже раздувает страницу, кладите в него только нужные поля;
- доставка: Brotli, HTTP/2 или HTTP/3,
<link rel="preload">для критического шрифта и LCP-картинки, 103 Early Hints.
Измеряйте TTFB на сервере, а LCP и INP по данным реальных пользователей, не только по Lighthouse.
Где спотыкаются
Называют lazy loading картинок и минификацию оптимизацией SSR. Это полезно, но относится к клиенту и сборке, про сервер тут ничего нет.
Читают cookies или заголовки в корневом layout. В Next.js это делает динамическими все страницы под ним, и кеш пропадает целиком.
Игнорируют hydration mismatch. Date.now(), Math.random() или проверка window в разметке дают разный HTML на сервере и клиенте, React перерисовывает участок заново, и выигрыш SSR теряется.