Мемоизация — это техника оптимизации, при которой результаты
выполнения функции сохраняются для последующего повторного использования
с теми же входными данными. В контексте Universal Router
мемоизация особенно полезна для снижения нагрузки при повторных
навигациях к одинаковым маршрутам или при частом вычислении разрешителей
(resolve functions).
В Universal Router каждый маршрут описывается объектом с
ключами path, action и опциональными
children. Ключевой механизм здесь — функция
action, которая выполняется при совпадении маршрута.
Мемоизация часто применяется именно на уровне этих функций:
const route = {
path: '/user/:id',
action: async ({ params }) => {
return fetchUser(params.id);
}
};
Если пользователь несколько раз открывает один и тот же путь
/user/123, то без мемоизации каждый вызов
action инициирует новый HTTP-запрос. Это неэффективно.
Мемоизация функции action может быть реализована с
помощью замыкания:
function memoizeAction(fn) {
const cache = new Map();
return async (context) => {
const key = JSON.stringify(context.params);
if (cache.has(key)) {
return cache.get(key);
}
const result = await fn(context);
cache.set(key, result);
return result;
};
}
const route = {
path: '/user/:id',
action: memoizeAction(async ({ params }) => {
return fetchUser(params.id);
})
};
Ключевые моменты:
params
маршрута.await.Для маршрутов с вложенными children мемоизация может
быть применена на нескольких уровнях:
const routes = [
{
path: '/dashboard',
action: memoizeAction(async () => {
return loadDashboardData();
}),
children: [
{
path: 'stats',
action: memoizeAction(async () => {
return loadStatsData();
})
},
{
path: 'reports',
action: memoizeAction(async () => {
return loadReportsData();
})
}
]
}
];
Особенности:
В некоторых случаях важно ограничить время жизни кэшированных данных:
function memoizeWithTTL(fn, ttl = 5000) {
const cache = new Map();
return async (context) => {
const key = JSON.stringify(context.params);
const now = Date.now();
if (cache.has(key)) {
const { value, expires } = cache.get(key);
if (now < expires) return value;
}
const result = await fn(context);
cache.set(key, { value: result, expires: now + ttl });
return result;
};
}
const route = {
path: '/user/:id',
action: memoizeWithTTL(async ({ params }) => {
return fetchUser(params.id);
}, 10000)
};
Преимущества такого подхода:
Иногда выгодно централизовать кэш для всего роутера:
const globalCache = new Map();
const memoizeGlobal = (fn) => async (context) => {
const key = context.pathname;
if (globalCache.has(key)) return globalCache.get(key);
const result = await fn(context);
globalCache.set(key, result);
return result;
};
const router = new UniversalRouter([
{ path: '/users', action: memoizeGlobal(loadUsers) },
{ path: '/settings', action: memoizeGlobal(loadSettings) }
]);
Особенности:
pathname.Мемоизация прекрасно сочетается с динамическим импортом компонентов:
const route = {
path: '/profile/:id',
action: memoizeAction(async ({ params }) => {
const module = await import('./Profile.js');
return module.renderProfile(params.id);
})
};
Мемоизация в Universal Router — мощный инструмент для
оптимизации производительности, снижения числа сетевых запросов и
ускорения рендеринга компонентов. Грамотная организация кэша позволяет
масштабировать маршрутизатор без потери скорости навигации.