Page.js предоставляет лёгкую и гибкую систему маршрутизации для одностраничных приложений на JavaScript. Одной из ключевых возможностей является использование middleware — функций, которые выполняются по цепочке при переходе по маршрутам. Middleware позволяют централизованно обрабатывать логику, общую для нескольких маршрутов, например, авторизацию, логирование или подготовку данных.
В Page.js middleware реализуются через функцию page(fn),
где fn — функция с сигнатурой (ctx, next).
Здесь ctx — объект контекста маршрута, содержащий путь,
параметры и состояние, а next — функция, вызывающая
следующий middleware в цепочке.
Middleware в Page.js имеет строгую форму:
function middleware(ctx, next) {
// Действия до передачи управления следующему middleware
console.log('Текущий путь:', ctx.path);
next(); // Передача управления следующему middleware
// Действия после возврата из следующего middleware (необязательно)
}
Ключевые моменты:
next() обязателен для
продолжения цепочки. Если не вызвать next(), последующие
middleware и обработчики маршрутов не выполнятся.async/await. Это позволяет выполнять запросы к серверу или
взаимодействовать с IndexedDB перед продолжением маршрута.Пример асинхронного middleware:
page(async (ctx, next) => {
ctx.user = await fetch('/api/current_user').then(res => res.json());
await next();
});
Композиция middleware — это организация нескольких функций в цепочку для одного или нескольких маршрутов. Page.js позволяет назначать middleware глобально или локально.
Глобальные middleware выполняются при любом переходе:
page((ctx, next) => {
console.log('Каждый маршрут будет проходить через этот middleware');
next();
});
Для конкретного маршрута можно указать несколько функций:
function auth(ctx, next) {
if (!ctx.user) {
page('/login');
} else {
next();
}
}
function loadData(ctx, next) {
ctx.data = fetchDataForRoute(ctx.path);
next();
}
page('/dashboard', auth, loadData, (ctx) => {
renderDashboard(ctx.data);
});
Здесь middleware выполняются последовательно,
передавая управление с помощью next(). Последняя функция —
это финальный обработчик маршрута, который рендерит страницу.
Page.js позволяет комбинировать глобальные и локальные middleware, создавая иерархию обработки:
// Глобальный middleware
page((ctx, next) => {
console.log('Глобальная проверка авторизации');
next();
});
// Локальные middleware для маршрута
page('/profile', auth, loadProfile, (ctx) => {
renderProfile(ctx.user);
});
В этом случае порядок выполнения будет следующим:
auth,
loadProfile).Такой подход позволяет разделять общие и специфические задачи, избегая дублирования кода.
Middleware может прерывать цепочку или перенаправлять пользователя, что полезно для контроля доступа или обработки ошибок:
function requireAdmin(ctx, next) {
if (!ctx.user || !ctx.user.isAdmin) {
page('/403');
} else {
next();
}
}
Также можно выполнять действия после выполнения следующего middleware:
page((ctx, next) => {
console.log('До выполнения следующих middleware');
next();
console.log('После выполнения следующих middleware');
});
Это позволяет создавать обёртки и слои обработки, похожие на паттерн middleware в Express.js.
Page.js поддерживает асинхронные middleware через
async/await, что критично для загрузки данных или проверки
сессии перед рендерингом:
page('/reports', async (ctx, next) => {
try {
ctx.reports = await fetch('/api/reports').then(res => res.json());
await next();
} catch (err) {
page('/error');
}
}, (ctx) => {
renderReports(ctx.reports);
});
Асинхронные middleware должны всегда вызывать
await next(), чтобы гарантировать выполнение
следующих функций в цепочке.
function requireAuth(ctx, next) {
if (!ctx.user) return page('/login');
next();
}
function preloadData(resource) {
return async (ctx, next) => {
ctx[resource] = await fetch(`/api/${resource}`).then(r => r.json());
await next();
};
}
page('/products', requireAuth, preloadData('products'), (ctx) => {
renderProducts(ctx.products);
});
page((ctx, next) => {
console.log(`[Navigation] Переход на ${ctx.path}`);
next();
});
Эти паттерны делают middleware мощным инструментом для масштабирования SPA, позволяя писать чистый и модульный код.
next() или перенаправлять
пользователя.Композиция middleware в Page.js позволяет строить гибкие и управляемые цепочки обработки маршрутов, комбинируя глобальные и локальные функции, синхронные и асинхронные операции, а также создавать мощные слои контроля доступа и подготовки данных. Это основной инструмент для организации структуры SPA и поддержания чистоты кода.