Universal Router — это гибкая библиотека маршрутизации для JavaScript, позволяющая реализовывать обработку HTTP-запросов как на стороне сервера, так и на клиенте. Библиотека опирается на концепцию маршрутов, которые представляют собой объекты с набором свойств, определяющих путь, условия сопоставления и обработчики.
Каждый маршрут в Universal Router описывается объектом вида:
const route = {
path: '/users/:id',
action: ({ params, query }) => {
return `Пользователь с ID: ${params.id}`;
}
};
Здесь ключевые элементы:
:id), регулярные выражения или wildcard
(*).При обработке HTTP-запроса Universal Router формирует объект
context, который передаётся во все функции
action. Стандартная структура:
{
pathname: '/users/123',
query: { search: 'test' },
params: { id: '123' },
route: { path: '/users/:id', action: [Function] },
baseUrl: ''
}
Контекст может быть расширен дополнительными данными, например, для передачи состояния аутентификации или сервисов.
Universal Router использует последовательное сопоставление маршрутов. Каждый маршрут проверяется в порядке объявления до первого успешного совпадения. Для сложных случаев применяется вложенная маршрутизация:
const router = new UniversalRouter([
{
path: '/users',
children: [
{
path: ':id',
action: ({ params }) => `Пользователь ${params.id}`
}
]
}
]);
Вложенные маршруты позволяют:
Маршруты могут содержать параметры, которые автоматически извлекаются
в context.params. Форматы:
/users/:id →
params.id/files/:name([a-z]+) → сопоставляет только буквы/files/* → сопоставляет
любое количество сегментов, результат доступен как
params['*']Пример с регулярным выражением:
{
path: '/posts/:year(\\d{4})/:month(\\d{2})',
action: ({ params }) => `Пост за ${params.month}/${params.year}`
}
action может возвращать промис, что позволяет выполнять
асинхронные операции, например, запросы к базе данных или API:
const route = {
path: '/data/:id',
action: async ({ params }) => {
const response = await fetch(`/api/data/${params.id}`);
return await response.json();
}
};
Universal Router автоматически обрабатывает промисы, возвращая результат при завершении.
Для обработки ошибок и отсутствующих маршрутов используется свойство
action в корневом маршруте или глобальные обработчики:
const router = new UniversalRouter([
{
path: '/users/:id',
action: ({ params }) => `User ${params.id}`
},
{
path: '(.*)', // wildcard для всех остальных путей
action: () => 'Страница не найдена'
}
]);
Такой подход обеспечивает:
Universal Router легко интегрируется с серверными фреймворками,
например, Express:
import express from 'express';
import UniversalRouter from 'universal-router';
const app = express();
const routes = [
{
path: '/users/:id',
action: ({ params }) => `Пользователь ${params.id}`
}
];
const router = new UniversalRouter(routes);
app.use(async (req, res) => {
try {
const result = await router.resolve({ pathname: req.path, query: req.query });
res.send(result);
} catch (err) {
res.status(404).send('Not Found');
}
});
app.listen(3000);
Здесь resolve принимает объект контекста с
pathname и query и возвращает результат
выполнения маршрута. Ошибки маршрутизации обрабатываются через
try/catch.
Universal Router не имеет встроенной концепции middleware, но её
можно реализовать через обёртки action или вложенные
маршруты:
const authMiddleware = async (context, next) => {
if (!context.user) throw new Error('Не авторизован');
return next();
};
const routes = [
{
path: '/dashboard',
action: async (context) => authMiddleware(context, async () => 'Dashboard')
}
];
Такой подход позволяет:
Query-параметры автоматически передаются в объект
context.query. Их можно использовать для фильтрации или
сортировки данных:
{
path: '/search',
action: ({ query }) => `Поиск по: ${query.q || 'ничего'}`,
}
Если нужно, query-параметры можно преобразовать или валидировать перед основной обработкой маршрута, расширяя контекст.
Universal Router поддерживает базовые URL, что полезно при вложенных маршрутах или при деплое приложения в подкаталогах:
const router = new UniversalRouter(routes, { baseUrl: '/app' });
Все пути маршрутов будут автоматически разрешаться относительно
/app, что облегчает миграцию и поддержку многослойных
приложений.
Universal Router обеспечивает мощную, при этом простую в использовании маршрутизацию, которая сочетает динамические пути, асинхронные действия и расширяемый контекст, позволяя строить современные серверные и клиентские приложения на JavaScript с гибкой обработкой HTTP-запросов.