Библиотека Page.js предоставляет легковесный способ организации клиентской маршрутизации в одностраничных приложениях (SPA). Основная задача — сопоставление URL с функциями-обработчиками и управление переходами между “страницами” без перезагрузки браузера.
В Page.js ключевым элементом является функция
page(path, callback), где:
path — строка, описывающая маршрут. Может содержать
параметры, например '/user/:id'.callback — функция, которая выполняется при совпадении
URL с маршрутом.page('/about', () => {
console.log('Страница о нас');
});
page('/user/:id', ctx => {
console.log('ID пользователя:', ctx.params.id);
});
Контекст ctx содержит информацию о текущем маршруте:
параметры, query-строку и путь.
В больших приложениях роутинг становится громоздким, если хранить все маршруты в одном файле. Разделение логики роутинга на модули помогает структурировать код и упростить поддержку.
Можно создать отдельные файлы для каждого блока приложения, например:
routes/home.js — домашняя страницаroutes/user.js — страницы пользователейroutes/admin.js — административные маршрутыКаждый модуль экспортирует функцию, которая регистрирует маршруты
через page:
// routes/home.js
export function homeRoutes() {
page('/', () => {
renderHomePage();
});
page('/about', () => {
renderAboutPage();
});
}
// routes/user.js
export function userRoutes() {
page('/user/:id', ctx => {
renderUserPage(ctx.params.id);
});
page('/user/:id/edit', ctx => {
renderEditUserPage(ctx.params.id);
});
}
Главный файл приложения импортирует все модули и инициализирует маршруты:
import { homeRoutes } from './routes/home.js';
import { userRoutes } from './routes/user.js';
homeRoutes();
userRoutes();
page();
Page.js поддерживает цепочки middleware, аналогично Express.js. Middleware полезны для выполнения общих действий перед обработкой конкретного маршрута: проверка авторизации, логирование, установка данных страницы.
function authMiddleware(ctx, next) {
if (!ctx.user) {
page.redirect('/login');
} else {
next();
}
}
page('/admin', authMiddleware, () => {
renderAdminDashboard();
});
Middleware можно применять глобально:
page('*', (ctx, next) => {
console.log('Переход на:', ctx.path);
next();
});
Page.js позволяет легко работать с динамическими сегментами пути:
page('/post/:postId', ctx => {
const postId = ctx.params.postId;
console.log('Показ поста:', postId);
});
Query-параметры извлекаются из ctx.querystring или через
URLSearchParams:
page('/search', ctx => {
const params = new URLSearchParams(ctx.querystring);
const query = params.get('q');
console.log('Поиск по:', query);
});
Для крупных приложений выгодно загружать маршруты динамически, только
когда они нужны. Используется import():
page('/admin', async () => {
const module = await import('./routes/admin.js');
module.adminRoutes();
});
Так достигается уменьшение размера основного бандла и ускорение загрузки.
Page.js предоставляет методы для программного управления навигацией:
page.show(path) — переход на путь без перезагрузки
страницыpage.redirect(path) — переход с заменой текущей записи
в историиdocument.querySelector('#go-home').addEventListener('click', () => {
page.show('/');
});
Можно управлять историей браузера и отслеживать события
popstate для интеграции с кнопками «назад/вперед».
Для несуществующих маршрутов можно создать fallback:
page('*', () => {
renderNotFoundPage();
});
Важно располагать такой маршрут в конце, чтобы он не перехватывал валидные URL.
page() — после
регистрации всех маршрутов, чтобы избежать дублирования.Page.js не занимается отображением, поэтому маршруты связываются с функциями рендеринга компонентов или шаблонов:
function renderHomePage() {
document.body.innerHTML = '<h1>Главная</h1>';
}
function renderUserPage(id) {
document.body.innerHTML = `<h1>Пользователь ${id}</h1>`;
}
Такой подход обеспечивает чистое разделение: Page.js отвечает за маршруты, а рендеринг полностью контролируется приложением.
Хотите, я могу сразу написать примеры структурированных проектов с Page.js, где показано разделение на модули, middleware и lazy-loading, с полностью рабочим кодом? Это будет как учебный проект для практики.