Перейти к содержимому

Верхняя навигация и маршрутизация страниц

Верхняя панель навигации — основной путь перемещения пользователя между функциональными разделами. EpoCanvas Docs хранит все навигационные элементы в одном конфигурационном файле: изменение в одном месте действует на весь сайт, при этом точно подсвечивается текущая страница и работает механизм перенаправления старых ссылок.


Центр настройки навигации (src/config/navigation.ts)

Все кнопки верхней навигации поддерживаются в виде декларативного массива в src/config/navigation.ts. Поля каждого элемента определены следующим образом:

// Определение свойств элемента навигации
export interface NavItem {
id: string; // уникальный идентификатор
labelKey: string; // имя ключа в многоязычном словаре переводов
defaultLabel: string; // текст, отображаемый по умолчанию (например, «Главная», «О продукте»)
href: string; // ссылка перехода или относительный путь
match?: (pathname: string) => boolean; // правило, определяющее, должна ли подсвечиваться эта кнопка на текущей странице
badge?: string; // дополнительная маленькая капсульная метка (например, номер версии "v1.2.0")
isExternal?: boolean; // является ли переход внешним (если да, открывается в новом окне)
}

Текущая официальная конфигурация (фрагмент)

export const navigationConfig: NavItem[] = [
{
id: 'home',
labelKey: 'nav.home',
defaultLabel: '首页',
href: '/',
match: (pathname: string) => pathname === '/' || pathname === '',
},
{
id: 'docs',
labelKey: 'nav.docs',
defaultLabel: '产品说明',
href: '/canvas/',
match: (pathname: string) =>
pathname === '/canvas' ||
pathname === '/canvas/' ||
pathname.includes('about') ||
pathname.includes('layout') ||
pathname.includes('search-engine') ||
pathname.includes('i18n') ||
pathname.includes('navigation'),
},
{
id: 'quickstart',
labelKey: 'nav.quickstart',
defaultLabel: '快速上手',
href: '/canvas/deployment/',
match: (pathname: string) => pathname.includes('deployment'),
},
// Далее следуют guide (правила написания), deploy (развёртывание), faq (частые вопросы)
// а также внешний элемент release, ведущий на GitHub Releases
];

Чтобы добавить или удалить элемент навигации, достаточно добавить или удалить запись в этом массиве; после сохранения локальный сервер разработки автоматически выполнит горячее обновление.


Правила динамической активации и подсветки

Если бы проверка сводилась к простому pathname.startsWith('/canvas'), то при открытии страницы быстрого старта /canvas/deployment/ могли бы подсветиться одновременно обе кнопки — «О продукте» и «Быстрый старт», что вводит в заблуждение.

Поэтому каждый элемент навигации объявляет свою зону подсветки функцией match:

  • при открытии главной страницы / активна только кнопка «Главная»;
  • при открытии обычных документов вроде /canvas/layout/, /canvas/about/ активируется кнопка «О продукте»;
  • при переходе на страницы с путём deployment исключительно активируется кнопка «Быстрый старт»;
  • активная кнопка имеет капсульную подложку цвета темы и заметно контрастирует с неактивными.

Добавляя новую страницу документации, не забудьте включить ключевое слово пути в правило match соответствующего элемента навигации, иначе верхняя панель не будет подсвечиваться правильно.


Внешние ссылки и поведение бейджа версии

Если элемент навигации ведёт на внешний сайт (например, на страницу Releases репозитория GitHub):

  1. задайте isExternal: true;
  2. система автоматически добавит ссылке защитные атрибуты target="_blank" rel="noopener noreferrer" и откроет её в новой вкладке;
  3. рядом с текстом появится маленький значок стрелки, направленной наружу (↗), предупреждающий читателя, что по клику он покинет текущий сайт.

Бейдж версии — капсула внутри кнопки; текст берётся из CURRENT_DOCS_VERSION в src/config/navigation.ts, который читает поле version файла package.json напрямую. При выпуске достаточно поправить только package.json, шапка обновится сама. Клик по бейджу открывает список релизов на GitHub. Полная процедура — в разделе Управление версиями и автоматизация.


Правила перенаправления страниц (astro.config.mjs)

В ходе развития проекта пути документов неизбежно меняются. Чтобы старые ссылки из закладок читателей не превращались в ошибку 404, зарегистрируйте соответствие старых и новых путей в таблице redirects в astro.config.mjs:

export default defineConfig({
redirects: {
// После семантического переименования путей разделов сайта все старые ссылки сохраняются и перенаправляются
'/canvas/rule-engine': '/canvas/cloudflare/',
'/canvas/dns-setup': '/canvas/layout/',
},
});

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

Почему на боевом сайте отдаётся 301

Страницы перенаправления, которые генерирует Astro, — это документы meta-refresh со статусом 200, и поисковики считают их второй копией цели. Cloudflare Pages читает файл _redirects в корне сайта раньше, чем статические файлы, поэтому cloudflareRedirectsFile() в astro.config.mjs после сборки пишет dist/_redirects из той же таблицы legacyRedirects:

/mail /canvas/ 301
/mail/ /canvas/ 301

Правила отличаются лишь завершающим слэшем: Cloudflare сопоставляет пути точно, и запрос со слэшем не попадает под правило без него, а значит упал бы на ту страницу 200. Локальный pnpm run preview файл _redirects не читает и по-прежнему использует страницу Astro, так что оба механизма сосуществуют.

Старый путь регистрируйте без завершающего слэша: Astro рендерит его как <старый путь>/index.html, а если добавить и вариант со слэшем в redirects, оба свернутся в один маршрут, о чем сборка сообщит предупреждением route collision (в следующем мажорном Astro это станет ошибкой).