Добавление метаданных

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

Каждый маршрут может содержать объект с метаданными, который передаётся вместе с обработчиком и становится доступным в момент активации маршрута.


Базовое добавление метаданных

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

const router = new Navigo('/');

router.on({
  '/dashboard': {
    uses: () => {
      console.log('Dashboard loaded');
    },
    as: 'dashboard',
    hooks: {},
    meta: {
      requiresAuth: true,
      title: 'Панель управления'
    }
  }
}).resolve();

Ключевые элементы:

  • uses — обработчик маршрута
  • as — имя маршрута
  • hooks — жизненный цикл маршрута
  • meta — объект метаданных

Доступ к метаданным внутри обработчика

Метаданные передаются через объект match, который доступен в обработчике:

router.on({
  '/profile': {
    uses: (match) => {
      console.log(match.route.meta);
    },
    meta: {
      requiresAuth: true,
      title: 'Профиль пользователя'
    }
  }
});

Структура доступа:

match.route.meta

Это позволяет использовать метаданные прямо в логике маршрута.


Практическое применение метаданных

1. Управление доступом (Auth Guard)

router.on({
  '/admin': {
    uses: (match) => {
      if (match.route.meta.requiresAuth && !isLoggedIn()) {
        router.navigate('/login');
        return;
      }

      renderAdmin();
    },
    meta: {
      requiresAuth: true
    }
  }
});

Метаданные выступают в роли декларативного слоя, отделяя конфигурацию от логики.


2. Динамическое изменение заголовка страницы

router.on({
  '/about': {
    uses: (match) => {
      document.title = match.route.meta.title;
      renderAbout();
    },
    meta: {
      title: 'О компании'
    }
  }
});

Позволяет централизованно управлять заголовками без дублирования.


3. SEO и описание страниц

router.on({
  '/blog': {
    uses: (match) => {
      setMetaDescription(match.route.meta.description);
      renderBlog();
    },
    meta: {
      description: 'Последние статьи и новости'
    }
  }
});

4. Управление анимациями переходов

router.on({
  '/gallery': {
    uses: (match) => {
      applyTransition(match.route.meta.transition);
      renderGallery();
    },
    meta: {
      transition: 'fade'
    }
  }
});

Использование метаданных с hooks

Navigo поддерживает хуки жизненного цикла маршрута (before, after, leave). Метаданные можно использовать и там:

router.on({
  '/settings': {
    uses: () => {
      renderSettings();
    },
    hooks: {
      before: (done, match) => {
        if (match.route.meta.requiresAuth && !isLoggedIn()) {
          router.navigate('/login');
          return;
        }
        done();
      }
    },
    meta: {
      requiresAuth: true
    }
  }
});

Хуки позволяют реализовать переиспользуемую логику, не загромождая основной обработчик.


Централизованная обработка метаданных

Вместо дублирования логики в каждом маршруте, можно вынести обработку метаданных в обёртку:

function handleRoute(handler) {
  return (match) => {
    const meta = match.route.meta || {};

    if (meta.requiresAuth && !isLoggedIn()) {
      router.navigate('/login');
      return;
    }

    if (meta.title) {
      document.title = meta.title;
    }

    handler(match);
  };
}

Применение:

router.on({
  '/dashboard': {
    uses: handleRoute(() => {
      renderDashboard();
    }),
    meta: {
      requiresAuth: true,
      title: 'Dashboard'
    }
  }
});

Динамические маршруты и метаданные

Метаданные работают и с параметризованными маршрутами:

router.on({
  '/user/:id': {
    uses: (match) => {
      const { id } = match.data;
      console.log(match.route.meta.section);
      renderUser(id);
    },
    meta: {
      section: 'user-profile'
    }
  }
});

Параметры (match.data) и метаданные (match.route.meta) используются независимо, но дополняют друг друга.


Наследование и переиспользование метаданных

Navigo не поддерживает наследование маршрутов «из коробки», но можно реализовать его вручную:

const authMeta = {
  requiresAuth: true
};

router.on({
  '/orders': {
    uses: renderOrders,
    meta: {
      ...authMeta,
      title: 'Заказы'
    }
  },
  '/cart': {
    uses: renderCart,
    meta: {
      ...authMeta,
      title: 'Корзина'
    }
  }
});

Такой подход уменьшает дублирование и делает конфигурацию чище.


Валидация метаданных

Поскольку meta — это произвольный объект, полезно вводить соглашения или проверки:

function validateMeta(meta) {
  if (meta.requiresAuth && typeof meta.requiresAuth !== 'boolean') {
    throw new Error('requiresAuth должен быть boolean');
  }
}

Использование:

router.on({
  '/secure': {
    uses: (match) => {
      validateMeta(match.route.meta);
      renderSecure();
    },
    meta: {
      requiresAuth: true
    }
  }
});

Хранение глобальных метаданных

Иногда требуется хранить общие значения:

const globalMeta = {
  appName: 'My App'
};

Использование внутри маршрута:

router.on({
  '/home': {
    uses: (match) => {
      document.title = `${match.route.meta.title} | ${globalMeta.appName}`;
    },
    meta: {
      title: 'Главная'
    }
  }
});

Отладка метаданных

Для диагностики удобно выводить структуру маршрута:

router.on({
  '/test': {
    uses: (match) => {
      console.log('Route:', match.route);
      console.log('Meta:', match.route.meta);
    },
    meta: {
      debug: true
    }
  }
});

Ограничения и особенности

  • Navigo не интерпретирует meta — это полностью пользовательская логика
  • Отсутствует встроенная схема или типизация
  • Метаданные не влияют на сопоставление маршрутов
  • Ответственность за обработку лежит на разработчике

Рекомендации по структуре метаданных

Хорошая практика — придерживаться единого формата:

meta: {
  requiresAuth: false,
  title: '',
  description: '',
  layout: 'default',
  transition: 'none'
}

Чёткая структура облегчает поддержку и масштабирование приложения.


Расширение через middleware-подход

Можно реализовать цепочку обработчиков:

const middlewares = [
  (match) => {
    if (match.route.meta.requiresAuth && !isLoggedIn()) {
      router.navigate('/login');
      return false;
    }
  },
  (match) => {
    if (match.route.meta.title) {
      document.title = match.route.meta.title;
    }
  }
];

function applyMiddlewares(handler) {
  return (match) => {
    for (const mw of middlewares) {
      if (mw(match) === false) return;
    }
    handler(match);
  };
}

Использование:

router.on({
  '/profile': {
    uses: applyMiddlewares(() => {
      renderProfile();
    }),
    meta: {
      requiresAuth: true,
      title: 'Профиль'
    }
  }
});

Интеграция с состоянием приложения

Метаданные можно связывать с глобальным состоянием:

router.on({
  '/theme': {
    uses: (match) => {
      setTheme(match.route.meta.theme);
    },
    meta: {
      theme: 'dark'
    }
  }
});

Итоговая роль метаданных

Метаданные в Navigo формируют слой декларативной конфигурации маршрутов, позволяя:

  • отделить бизнес-логику от описания маршрутов
  • централизовать поведение
  • упростить масштабирование
  • повысить читаемость кода

Гибкость meta делает его мощным инструментом при построении сложных SPA-приложений.