Page.js — это легковесная библиотека маршрутизации для одностраничных приложений (SPA) на JavaScript. Одной из ключевых задач при работе с SPA является эффективное управление ресурсами, чтобы минимизировать повторные сетевые запросы и ускорить загрузку страниц. Кеширование ресурсов позволяет хранить данные и шаблоны на стороне клиента, обеспечивая мгновенную реакцию интерфейса при переходах между маршрутами.
Page.js изначально не предоставляет встроенного кеша данных или шаблонов. Однако библиотека позволяет интегрировать любые подходы к кешированию за счет гибкой системы middleware и возможности работы с асинхронными функциями внутри маршрутов.
Основные варианты кеширования:
Кеширование шаблонов HTML
const templateCache = {};
function loadTemplate(name) {
if (templateCache[name]) return Promise.resolve(templateCache[name]);
return fetch(`/templates/${name}.html`)
.then(res => res.text())
.then(html => {
templateCache[name] = html;
return html;
});
}
page('/about', () => {
loadTemplate('about').then(html => {
document.getElementById('app').innerHTML = html;
});
});
Кеширование данных API
const dataCache = new Map();
function fetchData(endpoint) {
if (dataCache.has(endpoint)) return Promise.resolve(dataCache.get(endpoint));
return fetch(endpoint)
.then(res => res.json())
.then(data => {
dataCache.set(endpoint, data);
return data;
});
}
page('/users', () => {
fetchData('/api/users').then(users => renderUsers(users));
});
Кеширование компонентов или функций рендеринга
Page.js строится на обработчиках маршрутов, поэтому кеширование удобно интегрировать как middleware. Middleware выполняется до основного рендеринга, что позволяет предварительно загружать ресурсы.
Пример middleware с кешированием данных:
function cacheMiddleware(ctx, next) {
const endpoint = `/api${ctx.path}`;
if (dataCache.has(endpoint)) {
ctx.data = dataCache.get(endpoint);
next();
} else {
fetch(endpoint)
.then(res => res.json())
.then(data => {
dataCache.set(endpoint, data);
ctx.data = data;
next();
});
}
}
page('/products', cacheMiddleware, ctx => {
renderProducts(ctx.data);
});
ctx — объект контекста маршрута, позволяет передавать
данные между middleware и основным обработчиком.next() — передает управление следующему middleware или
обработчику маршрута.Такой подход позволяет централизованно управлять кешем и легко расширять его для новых маршрутов.
Кеширование без стратегии обновления может привести к устаревшим данным. Основные подходы к обновлению:
Time-to-Live (TTL)
const dataCache = new Map();
function fetchDataWithTTL(endpoint, ttl = 60000) {
const cached = dataCache.get(endpoint);
const now = Date.now();
if (cached && (now - cached.timestamp < ttl)) return Promise.resolve(cached.data);
return fetch(endpoint)
.then(res => res.json())
.then(data => {
dataCache.set(endpoint, { data, timestamp: now });
return data;
});
}
Ручное сбрасывание кеша
function invalidateCache(endpoint) {
dataCache.delete(endpoint);
}
Стратегия “Stale-While-Revalidate”
WeakMap) для кеширования
объектов, которые не должны блокировать сборку мусора.Такое комбинированное использование кеша с маршрутизацией Page.js позволяет существенно сократить время отклика приложения и уменьшить количество сетевых запросов, сохраняя при этом простоту и предсказуемость работы SPA.