Приоритеты роутов

В библиотеке Navigo маршрутизация строится на основе определения маршрутов и их соответствующих обработчиков. Одной из ключевых особенностей является механизм приоритизации роутов, который позволяет управлять тем, какой маршрут будет выбран при совпадении нескольких шаблонов URL.

По умолчанию, Navigo обрабатывает маршруты в порядке их добавления, однако более точный контроль достигается через специфичность маршрутов. Чем более конкретный маршрут, тем выше его приоритет. Это особенно важно при наличии динамических сегментов, wildcard-маршрутов и маршрутов с параметрами.


Специфичность маршрута

Специфичность определяется структурой шаблона маршрута:

  1. Статические сегменты (/about, /contact) имеют наивысший приоритет.
  2. Динамические сегменты (/user/:id) обрабатываются после статических.
  3. Optional-параметры (/post/:id?) снижают приоритет.
  4. Wildcard-сегменты (/files/*) имеют наименьший приоритет.

Пример:

const router = new Navigo('/');

router.on('/about', () => console.log('Страница About'));
router.on('/user/:id', ({ data }) => console.log('Пользователь', data.id));
router.on('/user/:id/profile', ({ data }) => console.log('Профиль пользователя', data.id));
router.on('/files/*', ({ data }) => console.log('Файлы', data));

В этом примере URL /user/42/profile будет сопоставлен с маршрутом /user/:id/profile, несмотря на то что /user/:id тоже подходит, поскольку первый маршрут более конкретен.


Управление приоритетами вручную

Иногда требуется явно задать порядок обработки маршрутов, особенно если несколько динамических шаблонов пересекаются. В Navigo можно использовать объект с опцией priority (доступно в последних версиях) при добавлении маршрута:

router.on({
  '/user/:id': { handler: ({ data }) => console.log('User', data.id), priority: 1 },
  '/user/:id/profile': { handler: ({ data }) => console.log('Profile', data.id), priority: 2 }
});

Значение priority влияет на то, какой маршрут будет выбран первым: чем выше число, тем выше приоритет. Это позволяет гарантировать выбор нужного обработчика при пересечении динамических шаблонов.


Пересечение wildcard и динамических маршрутов

Wildcard (*) маршруты подхватывают любой путь, который не соответствует другим шаблонам. Они идеально подходят для обработчиков ошибок или fallback-страниц, например:

router.on('/files/*', () => console.log('Fallback для файлов'));
router.on('/files/images/:name', ({ data }) => console.log('Изображение', data.name));

При переходе на /files/images/photo.jpg будет вызван второй маршрут, а не wildcard, поскольку конкретный шаблон имеет более высокий приоритет.


Приоритеты и регулярные выражения

Navigo поддерживает регулярные выражения для сегментов маршрута. При использовании регулярных выражений важно учитывать приоритет:

router.on('/product/:id(\\d+)', ({ data }) => console.log('Продукт', data.id));
router.on('/product/:slug([a-z-]+)', ({ data }) => console.log('Продукт по slug', data.slug));

URL /product/123 совпадет с первым маршрутом, а /product/example-product — со вторым. Navigo оценивает соответствие шаблона регулярному выражению при выборе маршрута, повышая приоритет более точного сопоставления.


Влияние порядка регистрации

Даже при использовании wildcard и динамических сегментов, порядок регистрации маршрутов влияет на их приоритет, если специфичность одинаковая. В случаях конфликта между маршрутами одинаковой структуры первый добавленный маршрут будет выбран первым, если не указана опция priority.


Рекомендации по проектированию маршрутов

  1. Размещать статические маршруты выше динамических.
  2. Использовать wildcard только для fallback-страниц.
  3. Присваивать явно приоритеты конфликтующим динамическим маршрутам.
  4. Следить за последовательностью регистрации маршрутов, особенно если используются похожие шаблоны.
  5. Использовать регулярные выражения для точного контроля соответствия, повышая специфичность маршрута.

Пример комплексной конфигурации

const router = new Navigo('/');

router.on({
  '/': { handler: () => console.log('Главная'), priority: 5 },
  '/about': { handler: () => console.log('О нас'), priority: 5 },
  '/user/:id/profile': { handler: ({ data }) => console.log('Профиль', data.id), priority: 4 },
  '/user/:id': { handler: ({ data }) => console.log('Пользователь', data.id), priority: 3 },
  '/files/*': { handler: ({ data }) => console.log('Файлы', data), priority: 1 }
});

В этой конфигурации Navigo будет последовательно проверять маршруты от наивысшего к низшему приоритету, что обеспечивает точное и предсказуемое сопоставление URL с обработчиками.