Демо
Демо-страница инструмента
Что такое SSR?
Демо-страница — это не пользовательский инструмент, а небольшой эталонный маршрут для проверки серверного рендеринга. Она показывает, как страница Next.js App Router может получить данные на сервере, встроить результат в первый HTML-ответ и загрузить переводы для текущей локали. Поэтому она полезна для проверки общей инфраструктуры: переменных окружения, подписанных серверных запросов, формы ответа API, маршрутизации по locale и загрузки переводов. Если эта страница работает, базовый путь SSR исправен, и можно переходить к более сложным инструментам. Если она падает, причину стоит искать в общей серверной конфигурации или соединении с API, а не в конкретном инструменте. Страница должна оставаться простой, чтобы быть надежным smoke-тестом после деплоя и обновлений фреймворка.
Как использовать
Как использовать
- Страница автоматически вызывает серверный API на бэкенде
- HTML содержит предварительно отрисованный контент — клиентский запрос не требуется
- Просмотрите данные, возвращённые API
- Идеально подходит для страниц, которым нужна SEO-оптимизация
Примечания для разработчиков
- Используйте эту страницу как smoke-тест для SSR, загрузки локалей, подписанных серверных запросов и подключения к API.
- Если страница не работает, проверьте общую конфигурацию сервера, прежде чем отлаживать конкретную страницу инструмента.
Применение
Технический принцип
Эта демо-страница построена на Next.js 16 App Router и по умолчанию использует серверный рендеринг (SSR). Когда пользователь запрашивает страницу, сервер Node.js сначала выполняет React-компонент, вызывает серверный API для получения данных, а затем возвращает полностью отрисованный HTML браузеру в одном ответе. Браузер сразу начинает разбор и отрисовку HTML, поэтому пользователи видят полный контент в первом кадре, не дожидаясь загрузки и выполнения JavaScript. Это резко контрастирует с традиционным клиентским рендерингом (CSR). При CSR сервер возвращает лишь почти пустую HTML-оболочку и ссылку на JS; браузер должен загрузить JS-бандл, выполнить инициализацию фреймворка, вызвать API для получения данных и только затем отрисовать страницу. С точки зрения пользователя это «пустой экран на какое-то время», и для поисковых краулеров это ещё хуже — большинство краулеров не выполняют JavaScript и видят лишь пустую оболочку. После SSR Next.js также внедряет фрагмент JavaScript для выполнения «гидратации»: связывания существующего DOM с деревом React-компонентов и привязки обработчиков событий, чтобы страница стала интерактивной. Полный поток: разбор HTML → загрузка CSS → загрузка JS → гидратация → интерактивность. Среди трёх Core Web Vitals, LCP (Largest Contentful Paint) и CLS (Cumulative Layout Shift) обычно лучше при SSR, а INP (Interaction to Next Paint) зависит от скорости гидратации и качества реализации обработчиков событий.
- Next.js App Router: страницы в App Router по умолчанию являются серверными компонентами, выполняются на сервере и автоматически возвращают HTML без дополнительной настройки.
- SSR против CSR: SSR обеспечивает быструю первую отрисовку и SEO-дружелюбность ценой серверных ресурсов; CSR подходит для внутренних дашбордов и других интерактивных сценариев, не требующих SEO.
- Поток первой отрисовки: разбор HTML → загрузка и отрисовка CSS → загрузка и выполнение JS → гидратация React → интерактивность страницы; каждый шаг влияет на LCP.
- SEO-дружелюбность для краулеров: основные краулеры, такие как Googlebot и Bingbot, читают текст HTML напрямую; SSR-вывод полного контента гарантирует покрытие индексации.
- Пороги Web Vitals: LCP < 2,5 с, INP < 200 мс, CLS < 0,1 — рекомендуемые Google пороги «хорошего» результата; SSR упрощает достижение LCP и CLS.
- Подписанные запросы: демо-страница вызывает серверный API через serverApiFetch на сервере, автоматически передавая X-Timestamp, X-Nonce и X-Sign для аутентификации.
Примеры
SSR (Server-Side Rendering)
// app/page.tsx (default Server Component)
export default async function Page() {
const data = await fetch('/api/info').then(r => r.json());
return <div>{data.title}</div>;
}
// HTML уже содержит <div>реальное содержимое</div>CSR (Client-Side Rendering)
'use client';
import { useEffect, useState } from 'react';
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/info').then(r => r.json()).then(setData);
}, []);
return <div>{data?.title || 'Loading...'}</div>;
}
// HTML первой отрисовки содержит только <div>Loading...</div>Сравнение скорости первой отрисовки
# SSR
FCP: 0.4s LCP: 0.8s TTI: 1.2s
SEO: краулеры получают полное содержимое сразу
# CSR
FCP: 0.6s LCP: 1.8s TTI: 2.4s
SEO: краулерам нужно выполнить JS, чтобы получить содержимоеЧасто задаваемые вопросы
Что именно демонстрирует эта страница?
Это эталонный маршрут серверного рендеринга (SSR), показывающий, как страница Next.js App Router может получать данные на сервере, встраивать результат в первый HTML-ответ и при этом подгружать корректные локализованные подписи. Это не пользовательский инструмент — это smoke-тест для разработчиков.
Данные подгружаются на сервере или в браузере?
На сервере. Страница вызывает serverApiFetch (с заголовками подписанного запроса из src/lib/sign.ts) внутри React Server Component, поэтому браузер получает HTML, в котором уже есть данные. При первой загрузке клиентского запроса нет.
Почему страница иногда показывает устаревшие данные?
Next.js может кешировать SSR-ответ в зависимости от настроек revalidate. Если нужны свежие данные при каждом запросе, задайте 'export const dynamic = "force-dynamic"' или передайте {cache: 'no-store'} в fetch. Демо-маршрут использует поведение по умолчанию, чтобы не усложнять пример.
Можно ли скопировать этот шаблон для своей страницы?
Да — для этого он и нужен. Маршрут показывает, как сочетать getTranslations из next-intl с серверной загрузкой данных и передавать результат в Client Component для интерактивности. Скопируйте layout.tsx и page.tsx и замените источник данных.
Зачем нужна подпись запросов для внутреннего API?
X-Timestamp / X-Nonce / X-Sign блокируют атаки с повторами и гарантируют, что запросы из публичной сети действительно приходят от доверенного клиента. Ключ подписи привязан к сессии у залогиненных пользователей и имеет значение по умолчанию в остальных случаях; см. реализацию в src/lib/sign.ts и src/lib/fetch.ts.
Будет ли эта страница в продакшен-сборках?
Она входит в развёрнутое приложение для справки, но не ссылается с главной страницы или списка инструментов и не объявляется как пользовательский инструмент. Воспринимайте её как документацию для разработчиков, отрендеренную как маршрут.
С чего начать, чтобы изучить структуру проекта?
Начните с layout.tsx и page.tsx этой страницы, затем прочитайте src/i18n.ts (конфигурация локалей), src/i18n/request.ts (загрузка глобальных переводов), src/lib/load-page-messages.ts (переводы по страницам) и src/lib/fetch.ts (обёртки для подписанных запросов).