Именование маршрутов в контексте Universal Router — это фундаментальный аспект архитектуры приложения, напрямую влияющий на читаемость кода, масштабируемость и предсказуемость поведения навигации. Грамотно выстроенная система имен позволяет избежать дублирования, упрощает поддержку и снижает вероятность логических ошибок.
Маршрут в Universal Router — это объект конфигурации, содержащий путь
(path), обработчик (action) и дополнительные
параметры. Имя маршрута не является обязательным свойством библиотеки,
однако на практике вводится как дополнительный уровень абстракции.
Использование строковых путей (/users/123) напрямую в
коде приводит к ряду проблем:
Именованные маршруты решают эти проблемы за счёт:
Обычно вводится объект-константа, содержащий все имена маршрутов:
export const ROUTES = {
HOME: 'home',
USERS: 'users',
USER_DETAIL: 'user_detail',
SETTINGS: 'settings',
};
Каждое значение — это уникальный идентификатор маршрута.
Далее маршруты связываются с именами:
const routes = [
{
name: ROUTES.HOME,
path: '/',
action: HomePage,
},
{
name: ROUTES.USERS,
path: '/users',
action: UsersPage,
},
{
name: ROUTES.USER_DETAIL,
path: '/users/:id',
action: UserDetailPage,
},
];
Используется вложенная структура для отражения логики приложения:
export const ROUTES = {
USERS: {
LIST: 'users.list',
DETAIL: 'users.detail',
EDIT: 'users.edit',
},
};
Преимущества:
Имена строятся по шаблону:
<сущность>.<действие>
Примеры:
user.listuser.createuser.updateorder.checkoutUSER_LIST
USER_DETAIL
ORDER_CHECKOUT
Подходит для небольших проектов, но хуже масштабируется.
Именованный маршрут должен быть независим от URL:
{
name: 'user.profile',
path: '/profile/:id',
}
При изменении пути:
path: '/users/:id/profile'
логика приложения остаётся неизменной, если используется имя маршрута.
Создаётся вспомогательная функция:
function generateUrl(name, params = {}) {
const route = routes.find(r => r.name === name);
if (!route) throw new Error('Route not found');
let path = route.path;
Object.keys(params).forEach(key => {
path = path.replace(`:${key}`, params[key]);
});
return path;
}
Использование:
generateUrl('user.detail', { id: 42 });
// /users/42
Иногда требуется определить имя маршрута по текущему URL:
function findRouteByPath(path) {
return routes.find(route => {
const regex = new RegExp(
'^' + route.path.replace(/:\w+/g, '\\w+') + '$'
);
return regex.test(path);
});
}
Для повышения надёжности:
export const ROUTES = {
HOME: 'home',
USER_DETAIL: 'user.detail',
} as const;
type RouteName = typeof ROUTES[keyof typeof ROUTES];
Функция генерации URL:
function generateUrl(name: RouteName, params?: Record<string, string>): string {
// ...
}
Маршруты с параметрами требуют согласованности:
{
name: 'post.comment',
path: '/posts/:postId/comments/:commentId',
}
Имена параметров должны:
Universal Router поддерживает вложенные маршруты:
const routes = [
{
path: '/users',
children: [
{
name: 'users.list',
path: '/',
},
{
name: 'users.detail',
path: '/:id',
},
],
},
];
Важно:
В больших приложениях маршруты разбиваются по модулям:
export const USER_ROUTES = {
LIST: 'user.list',
DETAIL: 'user.detail',
};
export const ADMIN_ROUTES = {
DASHBOARD: 'admin.dashboard',
};
Объединение:
export const ROUTES = {
...USER_ROUTES,
...ADMIN_ROUTES,
};
Ошибка:
name: 'detail'
Правильно:
user.detail
order.detail
product.detail
Каждое имя должно быть уникальным в пределах приложения.
Нельзя смешивать стили:
Плохо:
userList
user_detail
USER_EDIT
Хорошо:
user.list
user.detail
user.edit
Навигация через имена:
router.resolve({ name: 'user.detail', params: { id: 1 } });
или через обёртку:
navigate(ROUTES.USER_DETAIL, { id: 1 });
При динамической загрузке:
{
name: 'settings.profile',
path: '/settings/profile',
action: () => import('./pages/Profile'),
}
Имя остаётся стабильным, независимо от способа загрузки.
При изменении структуры:
Именованные маршруты упрощают тесты:
expect(generateUrl('user.detail', { id: 5 }))
.toBe('/users/5');
navigate('/users/1');
const path = '/users';
router.push('/users');
route1
page2
testRoute
Имя маршрута часто используется как ключ для метаданных:
const routeMeta = {
'user.detail': {
requiresAuth: true,
title: 'User Profile',
},
};
Имена маршрутов позволяют строить навигационные цепочки:
const breadcrumbs = {
'user.detail': ['home', 'users.list', 'user.detail'],
};
Имя маршрута остаётся неизменным:
user.detail
А путь меняется:
/en/users/:id
/ru/polzovateli/:id
При росте проекта:
Именование маршрутов становится не просто соглашением, а архитектурным инструментом, обеспечивающим управляемость и предсказуемость всей системы навигации.