Кеширование в контексте роутинга позволяет значительно повысить производительность приложения, особенно когда маршруты выполняют сложные операции или обращаются к внешним ресурсам. В Universal Router кеширование можно реализовать на нескольких уровнях: кеширование результатов обработчиков, кеширование промисов и сохранение промежуточных вычислений для повторного использования.
Каждый маршрут в Universal Router описывается объектом с ключами
path и action. Если результат работы
action не меняется при одинаковых входных данных, его можно
закешировать. Простейшая реализация кеша может выглядеть так:
import UniversalRouter from 'universal-router';
const cache = new Map();
const routes = [
{
path: '/user/:id',
async action(context) {
const cacheKey = `user:${context.params.id}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const user = await fetchUserFromAPI(context.params.id);
cache.set(cacheKey, user);
return user;
}
}
];
const router = new UniversalRouter(routes);
Ключевые моменты:
cacheKey формируется на основе параметров
маршрута.Universal Router полностью поддерживает асинхронные обработчики через промисы. Вместо кеширования окончательного результата можно кешировать сам промис, что предотвращает многократные параллельные запросы к одному ресурсу:
const promiseCache = new Map();
async function fetchUser(id) {
if (!promiseCache.has(id)) {
promiseCache.set(id, fetchUserFromAPI(id));
}
return promiseCache.get(id);
}
const routes = [
{
path: '/user/:id',
action: ({ params }) => fetchUser(params.id)
}
];
Преимущества:
Иногда результат маршрута зависит не только от параметров URL, но и от состояния приложения или времени. В таких случаях можно использовать условное кеширование:
const routes = [
{
path: '/posts',
async action(context) {
const cacheKey = 'posts';
const cacheData = cache.get(cacheKey);
if (cacheData && Date.now() - cacheData.timestamp < 60000) {
return cacheData.value;
}
const posts = await fetchPosts();
cache.set(cacheKey, { value: posts, timestamp: Date.now() });
return posts;
}
}
];
Особенности реализации:
timestamp) позволяет
реализовать автоматический ttl (time-to-live).Для крупных приложений часто имеет смысл интегрировать Universal Router с внешними кешами, такими как Redis или localStorage. Это позволяет:
Пример с localStorage:
function getCached(key) {
const cached = localStorage.getItem(key);
if (!cached) return null;
const data = JSON.parse(cached);
if (Date.now() - data.timestamp > 300000) return null; // 5 минут ttl
return data.value;
}
function setCached(key, value) {
localStorage.setItem(key, JSON.stringify({ value, timestamp: Date.now() }));
}
const routes = [
{
path: '/dashboard',
async action() {
const cacheKey = 'dashboard';
const cached = getCached(cacheKey);
if (cached) return cached;
const data = await fetchDashboardData();
setCached(cacheKey, data);
return data;
}
}
];
Выбор стратегии зависит от характера маршрута и приложения:
Рекомендации:
Кеширование должно учитывать возможность ошибок при асинхронных вызовах:
const routes = [
{
path: '/profile/:id',
async action({ params }) {
const cacheKey = `profile:${params.id}`;
try {
if (cache.has(cacheKey)) return cache.get(cacheKey);
const profile = await fetchProfile(params.id);
cache.set(cacheKey, profile);
return profile;
} catch (error) {
console.error('Ошибка при загрузке профиля:', error);
throw error; // Не сохраняем в кеш при ошибке
}
}
}
];
Кеширование в Universal Router — это гибкий инструмент, который позволяет улучшить производительность, снизить нагрузку на сервер и уменьшить задержки при навигации. Использование кешей промисов, TTL, условного хранения и интеграции с внешними хранилищами обеспечивает высокую эффективность работы маршрутов даже в сложных приложениях.