← Назад к вопросам

Что закэшируешь на Frontend для SSR?

2.0 Middle🔥 202 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Стратегия кэширования для SSR (Server-Side Rendering)

При SSR кэширование становится многоуровневой архитектурой, где мы балансируем между свежестью контента, производительностью сервера и скоростью отклика. Вот ключевые объекты для кэширования, от наиболее очевидных до продвинутых стратегий.

1. Кэширование HTML-страниц (полных или фрагментов)

Полные HTML-документы — основа SSR-кэша. Особенно эффективно для статичных или редко меняющихся страниц (лендинги, статьи, карточки товаров).

// Пример с Express + memory-cache
import cache from 'memory-cache';

app.get('/product/:id', async (req, res) => {
  const cacheKey = `page_${req.url}`;
  const cachedHtml = cache.get(cacheKey);
  
  if (cachedHtml) {
    return res.send(cachedHtml);
  }
  
  const html = await renderPage(req);
  cache.put(cacheKey, html, 5 * 60 * 1000); // TTL 5 минут
  res.send(html);
});

Фрагменты страниц (компонентное кэширование) в Next.js (ISR) или Nuxt:

  • Страницы с getStaticProps в Next.js
  • generate в Nuxt для статических роутов
  • Ключевой параметр — revalidate для фоновой ревалидации

2. Кэширование данных API (Data Cache)

Отделяем данные от разметки. Сервер рендерит с актуальными данными, но сами данные кэшируем.

// Пример стратегии stale-while-revalidate
async function getCachedData(key, fetchData, ttl = 300) {
  const cached = await redis.get(key);
  
  if (cached) {
    // Фоновая ревалидация
    fetchData().then(freshData => 
      redis.setex(key, ttl, JSON.stringify(freshData))
    );
    return JSON.parse(cached);
  }
  
  const freshData = await fetchData();
  await redis.setex(key, ttl, JSON.stringify(freshData));
  return freshData;
}

Что кэшируем:

  • Результаты API-запросов к CMS (контент)
  • Данные пользовательских сессий (но осторожно!)
  • Списки товаров/статей с пагинацией

3. Кэширование сборок и ассетов

SSR-бандлы — после сборки приложения можно кэшировать:

  • Рендеринговые функции (React renderToString, Vue renderToString)
  • Скомпилированные шаблоны
  • Результаты транспиляции (Babel/SWC)
// Webpack + память сервера
let cachedBundle;
async function getAppBundle() {
  if (cachedBundle) return cachedBundle;
  
  cachedBundle = await fs.promises.readFile('./dist/ssr-bundle.js');
  return cachedBundle;
}

4. Сессионное кэширование

Для персонализированного контента используем короткоживущие кэши:

  • HTML с пользовательскими данными (TTL 10-30 секунд)
  • Ключ кэша включает userId или sessionId
  • Инвалидация при logout или действиях пользователя

5. Интеллектуальная инвалидация

Кэширование бессмысленно без грамотной инвалидации.

Подходы:

  • TTL-based (время жизни) — простой, но "слепой"
  • Tag-based — пометка данных тегами, очистка по тегу
    // Пример: при обновлении товара инвалидируем все связанные страницы
    await redis.del('product:123', 'category:electronics', 'homepage');
    
  • On-demand Revalidation (Next.js) — вызов API-роута для регенерации

6. Распределенное кэширование (CDN + Edge)

Для глобальных приложений:

Пользователь → CDN (Edge Cache) → Origin Server (SSR)

Настройки CDN:

  • Cache-Control: public, s-maxage=60, stale-while-revalidate=300
  • Стратегия stale-while-revalidate на edge (Cloudflare Workers, Vercel Edge)
  • Геораспределенное кэширование HTML

7. Специфичные для фреймворков кэши

Next.js:

  • getStaticProps + revalidate (ISR)
  • unstable_cache() для данных
  • Роут-хендлеры с настройками кэширования

Nuxt:

  • useAsyncData с ключами кэширования
  • useFetch с опциями server: true
  • Nitro-хендлеры с cached: true

Практические рекомендации

Приоритеты кэширования:

  1. Статичный контент → длинный TTL (часы/дни)
  2. Полустатичный → средний TTL (минуты) + revalidate
  3. Персонализированный → короткий TTL (секунды) или отказ от кэша

Метрики для мониторинга:

  • Cache hit ratio (доля попаданий в кэш)
  • SSR время ответа p95/p99
  • Снижение нагрузки на backend-API

Опасные антипаттерны:

  • Кэширование с авторизацией в открытом кэше
  • Слишком долгий TTL для динамического контента
  • Отсутствие инвалидации при изменениях

Итог: Современный SSR-кэш — это многослойная система, где HTML-страницы, данные и ассеты кэшируются с разной стратегией. Удачная реализация снижает нагрузку на сервер в 10-100 раз, обеспечивая миллисекундные отклики даже при высоких нагрузках. Ключ — не просто кэшировать, а делать это избирательно с умной инвалидацией.