Создание подроутеров

Page.js — это небольшая и мощная библиотека для организации маршрутов на стороне клиента в приложениях на JavaScript. Помимо обычной маршрутизации, Page.js поддерживает создание подроутеров, которые позволяют структурировать маршруты более гибко, особенно в крупных приложениях с вложенными страницами и компонентами.

Подроутер — это отдельный экземпляр маршрутизатора, который обрабатывает только определённый набор маршрутов, изолированно от основного роутера. Он позволяет создавать модульную структуру маршрутов, улучшает читаемость кода и упрощает управление сложными навигационными сценариями.


Создание подроутера

Подроутер создаётся с помощью функции page(), аналогично основному роутеру, но внутри контекста определённого маршрута. Пример:

import page from 'page';

// Основной роутер
page('/', () => console.log('Главная'));
page('/users', () => console.log('Список пользователей'));

// Создание подроутера для маршрутов пользователей
const usersRouter = page();

// Определение подмаршрутов
usersRouter('/users/:id', ctx => {
    console.log(`Пользователь с ID: ${ctx.params.id}`);
});
usersRouter('/users/:id/edit', ctx => {
    console.log(`Редактирование пользователя с ID: ${ctx.params.id}`);
});

// Подключение подроутера к основному
page('/users/*', (ctx, next) => {
    usersRouter(ctx.path);
});

// Запуск основного роутера
page();

Ключевые моменты:

  • Подроутер — это отдельный экземпляр page(), который можно использовать для обработки подмаршрутов.
  • Основной роутер делегирует управление подмаршрутам через универсальный маршрут *.
  • В ctx подроутера сохраняется объект контекста с параметрами маршрута, query-параметрами и путём.

Контекст подроутера

Каждый подроутер получает свой собственный объект контекста ctx, который является расширением контекста основного роутера. Он содержит:

  • ctx.path — полный путь текущего запроса.
  • ctx.params — параметры маршрута, включая динамические сегменты.
  • ctx.querystring — строка запроса URL.
  • ctx.state — объект для хранения данных, доступных на протяжении обработки маршрутов.

Пример использования:

usersRouter('/users/:id', ctx => {
    const userId = ctx.params.id;
    const query = ctx.querystring;
    console.log(`ID: ${userId}, Query: ${query}`);
});

Подроутер может изменять ctx.state, передавая данные между middleware подроутера без вмешательства основного роутера.


Вложенные подроутеры

Подроутеры можно вкладывать друг в друга для обработки многоуровневых маршрутов:

const settingsRouter = page();

settingsRouter('/profile', ctx => console.log('Настройки профиля'));
settingsRouter('/security', ctx => console.log('Настройки безопасности'));

usersRouter('/users/:id/settings/*', (ctx, next) => {
    settingsRouter(ctx.path.replace(`/users/${ctx.params.id}/settings`, ''));
});

Особенности:

  • Вложенные подроутеры позволяют делить маршруты по функциональным блокам.
  • Путь, передаваемый в подроутер, часто требует удаления префикса родительского маршрута.
  • Подроутеры могут иметь свои middleware и обработчики событий независимо от основного роутера.

Middleware в подроутерах

Подроутеры поддерживают middleware, что позволяет выполнять промежуточные действия перед рендерингом компонента:

usersRouter('/users/:id', authMiddleware, ctx => {
    console.log(`Пользователь с ID: ${ctx.params.id} прошёл аутентификацию`);
});

function authMiddleware(ctx, next) {
    if (!ctx.state.user) {
        console.log('Не авторизован');
    } else {
        next();
    }
}

Преимущества middleware в подроутерах:

  • Локальное применение только к маршрутам подроутера.
  • Возможность реализовать проверки доступа, загрузку данных или логирование без загрязнения основного роутера.
  • Поддержка последовательного вызова через next().

Управление переходами и навигацией

Подроутеры можно использовать совместно с функцией page.show() для программной навигации:

usersRouter('/users/:id', ctx => {
    console.log('Загрузка данных пользователя');
});

// Переход к подмаршруту
page.show('/users/42');

Особенности навигации:

  • Подроутер не запускается автоматически; его нужно явно вызывать через родительский маршрут или page.show().
  • Переходы учитывают динамические параметры и query-параметры.
  • Подроутеры можно использовать для ленивой загрузки маршрутов в SPA, снижая нагрузку на основной роутер.

Применение подроутеров в больших приложениях

Подроутеры особенно полезны в больших SPA:

  • Модуляризация кода: отдельный подроутер для каждого раздела приложения (/users, /products, /settings).
  • Изоляция логики маршрутов: middleware, обработчики и состояния подроутера не пересекаются с другими разделами.
  • Упрощённая поддержка динамических маршрутов: легко добавлять новые подмаршруты без изменения основного роутера.
  • Ленивая загрузка компонентов: маршруты подроутеров можно подключать динамически, экономя ресурсы браузера.

Создание подроутеров в Page.js позволяет строить масштабируемую и поддерживаемую архитектуру клиентской маршрутизации, обеспечивая чистое разделение маршрутов, их контекстов и логики обработки.