Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Стратегия кэширования для 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, VuerenderToString) - Скомпилированные шаблоны
- Результаты транспиляции (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
Практические рекомендации
Приоритеты кэширования:
- Статичный контент → длинный TTL (часы/дни)
- Полустатичный → средний TTL (минуты) + revalidate
- Персонализированный → короткий TTL (секунды) или отказ от кэша
Метрики для мониторинга:
- Cache hit ratio (доля попаданий в кэш)
- SSR время ответа p95/p99
- Снижение нагрузки на backend-API
Опасные антипаттерны:
- Кэширование с авторизацией в открытом кэше
- Слишком долгий TTL для динамического контента
- Отсутствие инвалидации при изменениях
Итог: Современный SSR-кэш — это многослойная система, где HTML-страницы, данные и ассеты кэшируются с разной стратегией. Удачная реализация снижает нагрузку на сервер в 10-100 раз, обеспечивая миллисекундные отклики даже при высоких нагрузках. Ключ — не просто кэшировать, а делать это избирательно с умной инвалидацией.