Feature-based routing в TanStack Router представляет собой подход к организации маршрутов в приложении на основе функциональных областей, а не строго по иерархии URL. Такой метод особенно удобен для крупных приложений, где разделение маршрутов по функциям повышает читаемость кода и облегчает поддержку.
Модульность Каждый функциональный блок приложения (например, авторизация, панель пользователя, управление продуктами) оформляется как отдельный модуль, включающий собственные маршруты, компоненты и логику.
Локальные маршруты Маршруты внутри модуля определяются локально и экспортируются как массив или объект. Это позволяет легко подключать их к корневому маршрутизатору, не засоряя глобальное пространство имен.
Lazy Loading и Code Splitting Feature-based routing естественно интегрируется с ленивой загрузкой. Каждый функциональный блок можно загружать динамически при необходимости, что уменьшает размер начального бандла и ускоряет первую загрузку приложения.
Пример структуры модуля для управления пользователями:
src/features/users/
├── routes.js
├── components/
│ ├── UserList.jsx
│ └── UserDetail.jsx
└── hooks/
└── useUserData.js
В файле routes.js определяется набор маршрутов для
данного блока:
import { createRoute } from '@tanstack/router';
import UserList from './components/UserList';
import UserDetail from './components/UserDetail';
export const usersRoutes = [
createRoute({
path: 'users',
component: UserList,
children: [
createRoute({
path: ':userId',
component: UserDetail,
}),
],
}),
];
path указывает путь внутри
модуля.component привязывает React-компонент
к маршруту.children позволяет вложить
подмаршруты, не смешивая их с глобальными маршрутами.После определения всех feature-модулей их маршруты объединяются в корневом роутере:
import { createRouter } from '@tanstack/router';
import { usersRoutes } from './features/users/routes';
import { productsRoutes } from './features/products/routes';
const router = createRouter({
routes: [
...usersRoutes,
...productsRoutes,
],
});
export default router;
Такой подход обеспечивает:
TanStack Router поддерживает асинхронные компоненты, что упрощает интеграцию динамически загружаемых блоков:
import { createRoute } from '@tanstack/router';
import { lazy } from 'react';
const UserList = lazy(() => import('./components/UserList'));
const UserDetail = lazy(() => import('./components/UserDetail'));
export const usersRoutes = [
createRoute({
path: 'users',
component: UserList,
children: [
createRoute({
path: ':userId',
component: UserDetail,
}),
],
}),
];
Использование React.Suspense на уровне маршрутизатора
позволяет корректно отображать индикатор загрузки для каждого
feature-модуля.
Feature-based routing хорошо сочетается с локальными состояниями модулей. Каждый модуль может иметь собственные хуки и сторы, а глобальное состояние объединяет только критически важные данные.
Пример: useUserData.js внутри модуля пользователей:
import { useState, useEffect } from 'react';
import { fetchUserList, fetchUserById } from './api';
export function useUserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetchUserList().then(setUsers);
}, []);
return users;
}
export function useUserDetail(userId) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUserById(userId).then(setUser);
}, [userId]);
return user;
}
Локальное управление состоянием упрощает модульное тестирование и уменьшает взаимозависимости между функциональными блоками.
Для передачи данных между модулями можно использовать:
Пример передачи состояния через query-параметр:
createRoute({
path: 'products',
component: ProductList,
searchSchema: {
category: String,
},
});
В этом случае модуль продуктов может автоматически получать
category из URL, сохраняя независимость от других
модулей.
Этот подход особенно полезен в масштабных SPA, где рост числа маршрутов и компонентов может быстро сделать проект трудно поддерживаемым.
Feature-based routing в TanStack Router обеспечивает современную, масштабируемую архитектуру маршрутизации, которая делает проект более структурированным, производительным и удобным для командной разработки.