В библиотеке Universal Router управление маршрутами
строится вокруг структуры объектов маршрутов, где каждый маршрут может
содержать дочерние маршруты через свойство children. Для
сложных приложений с множеством страниц или компонентов критически важна
оптимизация загрузки кода, чтобы минимизировать первоначальный вес
бандла. Ленивая загрузка (lazy loading) позволяет подгружать код только
при обращении к конкретному маршруту, снижая время первой загрузки
приложения.
Типичная конфигурация вложенных маршрутов выглядит так:
const routes = [
{
path: '/dashboard',
action: () => import('./pages/DashboardPage.js'),
children: [
{
path: '/analytics',
action: () => import('./pages/AnalyticsPage.js')
},
{
path: '/reports',
action: () => import('./pages/ReportsPage.js')
}
]
}
];
Здесь ключевые моменты:
path — путь маршрута.action — функция, возвращающая
компонент или промис с модулем. Использование динамического
import() обеспечивает ленивую загрузку.children — массив вложенных маршрутов.
Каждый дочерний маршрут также может содержать свой action и
свои children.Universal Router позволяет возвращать промис из action.
Это даёт возможность обрабатывать асинхронные импорты компонентов:
const router = new UniversalRouter(routes);
router.resolve('/dashboard/analytics')
.then(module => {
const AnalyticsPage = module.default;
AnalyticsPage.render();
})
.catch(err => console.error(err));
Важно, что вложенные маршруты автоматически наследуют контекст родителя, что позволяет организовывать маршрутизацию без дублирования данных.
children для динамической загрузкиДля более сложных приложений имеет смысл использовать функцию
children для ленивой загрузки не только компонентов, но и
самих конфигураций вложенных маршрутов:
const routes = [
{
path: '/settings',
action: () => import('./pages/SettingsPage.js'),
children: async () => {
const settingsRoutes = await import('./routes/settingsRoutes.js');
return settingsRoutes.default;
}
}
];
Особенности такого подхода:
router.resolve.Контекст Universal Router передаётся через объект
context при вызове router.resolve(). В случае
ленивой загрузки вложенных маршрутов важно правильно прокидывать этот
контекст:
const context = { user: { name: 'Alice' } };
router.resolve('/settings/profile', context)
.then(module => {
const ProfilePage = module.default;
ProfilePage.init(context.user);
});
Вложенные маршруты могут использовать этот контекст без дополнительной настройки, что позволяет строить авторизацию, локализацию и другие глобальные функции.
Для крупного приложения с несколькими уровнями маршрутов структура может выглядеть так:
const routes = [
{
path: '/',
action: () => import('./pages/HomePage.js')
},
{
path: '/app',
action: () => import('./pages/AppPage.js'),
children: async () => [
{
path: '/projects',
action: () => import('./pages/ProjectsPage.js'),
children: async () => {
const projectRoutes = await import('./routes/projectRoutes.js');
return projectRoutes.default;
}
},
{
path: '/team',
action: () => import('./pages/TeamPage.js')
}
]
}
];
Такой подход:
import() только для
тяжёлых компонентов — маленькие компоненты можно включать в
основной бандл.catch у промиса, возвращаемого
router.resolve().children только при
необходимости — лишние асинхронные вызовы замедляют навигацию
без ощутимой выгоды.Комбинация асинхронного action и функции
children позволяет:
Такой подход является стандартной практикой для приложений на Universal Router, где важна производительность и масштабируемость.