Next.js 15 в Hikasami: Глубокая оптимизация рендеринга, загрузки данных и производительности
- пятница, 28 февраля 2025 г. в 00:00:08
В эпоху цифрового контента каждая миллисекунда загрузки страницы может существенно повлиять на пользовательский опыт. В Hikasami, платформе, предоставляющей потоковое аниме и азиатские медиа для пользователей СНГ, наша цель — обеспечить мгновенную загрузку страниц, минимизировать задержки, а также гарантировать актуальность данных. Для этого мы внедрили Next.js 15, который открыл перед нами возможности глубокой оптимизации:
Оптимизированное серверное рендеринг (SSR) с прогрессивным кешированием.
Гибридная стратегия кеширования API и динамическое обновление данных.
Использование Edge Functions для минимизации задержек по регионам.
Гибкая адаптация Gravity UI под SSR.
Максимальная оптимизация загрузки видео контента.
Эта статья представляет детальный технический разбор внедренных решений и стратегий оптимизации, направленных на повышение производительности и отказоустойчивости платформы.
Server‑Side Rendering (SSR) позволяет Next.js динамически формировать HTML на сервере перед отправкой клиенту. Однако использование SSR без продуманного кеширования может приводить к высокой нагрузке на сервер и увеличению Time To First Byte (TTFB).
Теоретическое обоснование выбора SSR
SSR обладает рядом преимуществ перед традиционным клиентским рендерингом (CSR, Client‑Side Rendering) и статической генерацией (SSG, Static Site Generation):
Более высокая индексируемость контента — поисковые системы получают уже отрендеренный HTML, что улучшает SEO.
Лучший UX для пользователей с медленным интернетом — контент загружается сразу, а не после получения и исполнения JavaScript.
Более быстрая начальная загрузка по сравнению с CSR, так как нет необходимости в полном выполнении JavaScript до появления контента.
Однако без должного кеширования SSR может привести к нагрузке на сервер и значительным задержкам в обработке запросов. Именно поэтому мы реализовали прогрессивное кеширование с использованием Redis и CDN.
Проблемы, с которыми мы столкнулись:
Высокий TTFB на страницах с динамическими данными.
Повышенная нагрузка на базу данных (PostgreSQL) при частых запросах.
Задержки при доступе пользователей из отдалённых регионов.
Анализ альтернативных подходов
Классический SSR без кеширования — отказались из‑за высокой нагрузки на сервер и значительного увеличения TTFB.
Полностью статическая генерация (SSG) — подходит для контента, который редко обновляется, но у нас динамические данные (рейтинги, новинки, рекомендации).
Гибридный подход (SSR + ISR + CDN) — оказался оптимальным, так как позволил кешировать контент и обновлять его по мере необходимости.
Наше решение:
Внедрение Redis для кеширования HTML‑ответов SSR.
Оптимизация пула соединений PostgreSQL через pgxpool.
Использование Edge Functions для распределённого рендеринга.
Настройка Cloudflare CDN для агрессивного кеширования API и статики.
Пример SSR с кешированием в Redis:
import { getAnimeById } from '@/lib/api';
import { redis } from '@/lib/redis';
export async function getServerSideProps(context) {
const { id } = context.params;
const cacheKey = `anime_${id}`;
let anime = await redis.get(cacheKey);
if (!anime) {
anime = await getAnimeById(id);
await redis.set(cacheKey, JSON.stringify(anime), 'EX', 60); // Кеш на 60 сек
}
return { props: { anime: JSON.parse(anime) } };
}
ISR позволяет Next.js регенерировать страницы на лету без полной пересборки проекта.
Анализ альтернативных решений
Чистый SSR — может перегрузить сервер при высоком количестве запросов.
Чистый SSG — требует полной пересборки сайта для обновления данных.
ISR с гибкой стратегией кеширования — позволяет обновлять данные на основе гибридного подхода.
Наше гибридное решение кеширования:
Динамическое обновление популярных страниц с частыми запросами.
Менее популярные страницы обновляются реже.
Ручное триггерное обновление через WebSockets.
Гибридное кеширование ISR + CDN для минимизации серверных нагрузок.
Пример ISR с динамическим обновлением:
export async function getStaticProps() {
const res = await fetch('https://api.hikasami.com/anime/top');
const topAnime = await res.json();
return {
props: { topAnime },
revalidate: 30, // Обновление раз в 30 сек
};
}
Gravity UI изначально не поддерживала SSR, что приводило к ошибкам гидратации.
Анализ альтернативных решений
Использование другой UI‑библиотеки (например, Chakra UI) — потребовало бы значительного рефакторинга проекта.
Ожидание исправлений в Gravity UI — могло занять месяцы, а нам требовалось решение «здесь и сейчас».
Форк и адаптация Gravity UI под SSR — оказалось наиболее эффективным решением.
Наше решение:
Перенос кода библиотеки в проект и адаптация под SSR.
Глубокая переработка серверного рендеринга компонентов.
На текущий момент разработка Next.js‑ветки Gravity UI активизировалась, но наше пользовательское решение остаётся стабильным и отказоустойчивым.
Переход на Next.js 15 позволил:
Снизить TTFB на 40%.
Оптимизировать кеширование API и SSR.
Гибко адаптировать Gravity UI под SSR.
Максимально ускорить загрузку видео контента через CDN.
Внедрение AI‑рекомендаций на основе пользовательского поведения.
Улучшение мобильного UX и расширение PWA‑функциональности.
Дальнейшее исследование распределённого рендеринга через Edge Functions.