Генерация URL из маршрутов

Universal Router — это гибкая библиотека маршрутизации для JavaScript, позволяющая строить маршруты с динамическими параметрами и вложенной структурой. Одной из ключевых возможностей является генерация URL из маршрутов, что особенно важно при работе с клиентской навигацией, ссылками и редиректами.

Маршруты и параметры

Маршрут в Universal Router определяется объектом с обязательным полем path и функцией action. Простейший пример:

const routes = [
  {
    path: '/users/:id',
    action: ({ params }) => `Пользователь ${params.id}`
  }
];

Здесь :id — динамический сегмент. Чтобы сгенерировать URL с конкретным значением параметра, нужно использовать соответствующий механизм построения URL.

Метод path и его назначение

Universal Router не предоставляет встроенного метода generate в ядре. Для генерации URL используют сторонние утилиты, совместимые с синтаксисом маршрутов Universal Router, например, библиотеку path-to-regexp. Она позволяет:

  • Конвертировать строку маршрута в функцию генерации URL.
  • Подставлять динамические параметры.
  • Поддерживать опциональные и повторяющиеся сегменты.

Пример интеграции:

import { compile } from 'path-to-regexp';

const routePath = '/users/:id';
const toPath = compile(routePath);

const url = toPath({ id: 42 });
console.log(url); // '/users/42'

Вложенные маршруты

Universal Router позволяет строить вложенные маршруты, где путь родителя может использоваться как базовый для дочерних маршрутов. При генерации URL это учитывается через рекурсивную сборку путей.

const routes = [
  {
    path: '/users',
    children: [
      {
        path: ':id/profile',
        action: ({ params }) => `Профиль пользователя ${params.id}`
      }
    ]
  }
];

Для генерации URL вложенного маршрута можно написать вспомогательную функцию, которая собирает путь от корня до нужного узла и подставляет параметры:

import { compile } from 'path-to-regexp';

function generateUrl(route, params) {
  let pathSegments = [];
  let current = route;

  while (current) {
    if (current.path) pathSegments.unshift(current.path);
    current = current.parent; // предполагаем, что у каждого маршрута есть ссылка на родителя
  }

  const fullPath = pathSegments.join('/');
  const toPath = compile(fullPath);
  return toPath(params);
}

Опциональные параметры и query-параметры

Path-to-regexp поддерживает опциональные сегменты через знак ? и повторяющиеся сегменты через * или +. Например:

const routePath = '/posts/:id/:tab?';
const toPath = compile(routePath);

console.log(toPath({ id: 10 })); // '/posts/10'
console.log(toPath({ id: 10, tab: 'comments' })); // '/posts/10/comments'

Query-параметры обычно формируются отдельно, так как path-to-regexp обрабатывает только путь. Для генерации полного URL с query-параметрами используют стандартный API URLSearchParams:

const params = { page: 2, sort: 'asc' };
const query = new URLSearchParams(params).toString();
const fullUrl = `${toPath({ id: 10 })}?${query}`;
console.log(fullUrl); // '/posts/10?page=2&sort=asc'

Генерация ссылок для клиентской навигации

При использовании Universal Router на клиенте, например в SPA, часто требуется динамическое построение ссылок в компонентах. Для этого создаются функции-помощники:

function createLink(route, params, query = {}) {
  const url = generateUrl(route, params);
  const queryString = new URLSearchParams(query).toString();
  return queryString ? `${url}?${queryString}` : url;
}

const link = createLink(profileRoute, { id: 42 }, { ref: 'dashboard' });
console.log(link); // '/users/42/profile?ref=dashboard'

Резюме по правилам генерации URL

  • Использовать path-to-regexp для подстановки динамических сегментов.
  • Для вложенных маршрутов формировать полный путь от корня.
  • Опциональные сегменты обозначать ?, повторяющиеся — * или +.
  • Query-параметры формировать отдельно через URLSearchParams.
  • Создавать вспомогательные функции для генерации ссылок, чтобы минимизировать дублирование кода.

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

  • Каждому маршруту можно добавить поле name для удобной генерации URL по имени маршрута.
  • Для сложных SPA удобно поддерживать карту маршрутов с ссылками на родителя, чтобы рекурсивно собирать полный путь.
  • Поддержка вложенности упрощает изменение базового пути без необходимости правки всех дочерних маршрутов.

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