Skip to content

Маршрутизация

Маршрутизация на основе файлов

VitePress использует маршрутизацию на основе файлов, что означает, что сгенерированные HTML-страницы отображаются на основе структуры папок исходных файлов Markdown. Например, при следующей структуре папок:

.
├─ guide
│  ├─ getting-started.md
│  └─ index.md
├─ index.md
└─ prologue.md

Сгенерированные HTML-страницы будут выглядеть так:

index.md                  -->  /index.html (доступна по адресу /)
prologue.md               -->  /prologue.html
guide/index.md            -->  /guide/index.html (доступна по адресу /guide/)
guide/getting-started.md  -->  /guide/getting-started.html

Полученный HTML можно разместить на любом веб-сервере, который может обслуживать статические файлы.

Корневая директория и директория с исходными файлами

В файловой структуре проекта VitePress есть два важных понятия: корень проекта и директория с исходными файлами.

Корень проекта

Корень проекта — это место, где VitePress будет пытаться искать специальный каталог .vitepress. Директория .vitepress — это зарезервированное место для конфигурационного файла VitePress, кэша dev-сервера, результатов сборки и дополнительного кода настройки темы.

Когда вы запускаете vitepress dev или vitepress build из командной строки, VitePress будет использовать текущий рабочий каталог в качестве корня проекта. Чтобы указать подкаталог в качестве корневого, нужно передать команде относительный путь. Например, если ваш проект VitePress находится в папке ./docs, вам следует выполнить команду vitepress dev docs:

.
├─ docs                    # корень проекта
│  ├─ .vitepress           # директория с настройками
│  ├─ getting-started.md
│  └─ index.md
└─ ...
sh
vitepress dev docs

В результате получится следующее сопоставление источника с HTML:

docs/index.md            -->  /index.html (доступна по адресу /)
docs/getting-started.md  -->  /getting-started.html

Директория с исходными файлами

Директория с исходными файлами — это место, где хранятся ваши исходные файлы Markdown. По умолчанию она совпадает с корнем проекта. Однако вы можете настроить её с помощью параметра srcDir.

Опция srcDir разрешается относительно корня проекта. Например, с помощью srcDir: 'src', ваша файловая структура будет выглядеть следующим образом:

.                          # корень проекта
├─ .vitepress              # директория с настройками
└─ src                     # директория с исходными файлами
   ├─ getting-started.md
   └─ index.md

Итоговое сопоставление исходного кода с HTML:

src/index.md            -->  /index.html (доступна по адресу /)
src/getting-started.md  -->  /getting-started.html

Связи между страницами

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

md
<!-- Будут работать -->

[Первые шаги](./getting-started)
[Первые шаги](../guide/getting-started)

<!-- Не будут работать -->

[Первые шаги](./getting-started.md)
[Первые шаги](./getting-started.html)

Узнайте больше о ссылках на такие ресурсы, как изображения, в главе Обработка ресурсов.

Ссылки на страницы, не принадлежащие VitePress

Если вы хотите создать ссылку на страницу вашего сайта, которая не создана VitePress, вам нужно будет либо использовать полный URL-адрес (откроется в новой вкладке), либо явно указать цель:

Разметка

md
[Ссылка на pure.html](/pure.html){target="_self"}

Результат

Ссылка на pure.html

Примечание

В ссылках Markdown к URL-адресу автоматически добавляется значение параметра base. Это означает, что если вы хотите создать ссылку на страницу за пределами base, вам понадобится что-то вроде ../../pure.html в ссылке (разрешаемой браузером относительно текущей страницы).

Альтернативно можно напрямую использовать синтаксис тега ссылки:

md
<a href="/pure.html" target="_self">Ссылка на pure.html</a>

Создание чистого URL-адреса

Требуется поддержка сервера

Для обслуживания чистых URL-адресов с помощью VitePress требуется поддержка на стороне сервера.

По умолчанию VitePress разрешает входящие ссылки на URL-адреса, заканчивающиеся на .html. Однако некоторые пользователи могут предпочесть «Чистые URL-адреса» без расширения .html — например, example.com/path вместо example.com/path.html.

Некоторые серверы или хостинговые платформы (например, Netlify, Vercel, GitHub Pages) предоставляют возможность сопоставлять URL-адрес типа /foo с /foo.html, если он существует, без перенаправления:

Если эта функция вам доступна, вы также можете включить собственную опцию конфигурации VitePress cleanUrls, чтобы обеспечить следующее поведение:

  • Входящие ссылки между страницами генерируются без расширения .html.
  • Если текущий путь заканчивается на .html, маршрутизатор выполнит перенаправление на стороне клиента на путь без расширений.

Однако если вы не можете настроить свой сервер с такой поддержкой, вам придётся вручную прибегнуть к следующей структуре каталогов:

.
├─ getting-started
│  └─ index.md
├─ installation
│  └─ index.md
└─ index.md

Перезапись маршрутов

Вы можете настроить сопоставление между структурой исходного каталога и создаваемыми страницами. Это полезно, когда у вас сложная структура проекта. Допустим, у вас есть монорепо с несколькими пакетами, и вы хотите поместить документацию вместе с исходными файлами, как это сделано здесь:

.
├─ packages
│  ├─ pkg-a
│  │  └─ src
│  │      ├─ pkg-a-code.ts
│  │      └─ pkg-a-docs.md
│  └─ pkg-b
│     └─ src
│         ├─ pkg-b-code.ts
│         └─ pkg-b-docs.md

И вы хотите, чтобы страницы VitePress генерировались следующим образом:

packages/pkg-a/src/pkg-a-docs.md  -->  /pkg-a/index.html
packages/pkg-b/src/pkg-b-docs.md  -->  /pkg-b/index.html

Этого можно добиться, настроив опцию rewrites следующим образом:

ts
// .vitepress/config.js
export default {
  rewrites: {
    'packages/pkg-a/src/pkg-a-docs.md': 'pkg-a/index.md',
    'packages/pkg-b/src/pkg-b-docs.md': 'pkg-b/index.md'
  }
}

Опция rewrites также поддерживает динамические параметры маршрута. В приведённом выше примере, если у вас много пакетов, перечислять все пути было бы скучно. Учитывая, что все они имеют одинаковую структуру файлов, можно упростить конфигурацию следующим образом:

ts
export default {
  rewrites: {
    'packages/:pkg/src/(.*)': ':pkg/index.md'
  }
}

Пути перезаписи компилируются с помощью пакета path-to-regexp — обратитесь к его документации за более сложным синтаксисом.

Относительные ссылки с переписыванием

Когда переписывание включено, относительные ссылки должны быть основаны на переписанных путях. Например, чтобы создать относительную ссылку с packages/pkg-a/src/pkg-a-code.md на packages/pkg-b/src/pkg-b-code.md, нужно использовать:

md
[Ссылка на PKG B](../pkg-b/pkg-b-code)

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

Вы можете создать множество страниц, используя один файл Markdown и динамические данные. Например, вы можете создать файл packages/[pkg].md, который будет генерировать соответствующую страницу для каждого пакета в проекте. Здесь сегмент [pkg] является параметром маршрута, который отличает каждую страницу от других.

Файл загрузчика путей

Поскольку VitePress — это генератор статических сайтов, возможные пути страниц должны быть определены во время сборки. Поэтому динамическая маршрутная страница должна сопровождаться файлом загрузчика путей. Для packages/[pkg].md нам понадобится packages/[pkg].paths.js (.ts также поддерживается):

.
└─ packages
   ├─ [pkg].md         # шаблон маршрута
   └─ [pkg].paths.js   # загрузчик путей маршрута

Загрузчик путей должен предоставлять объект с методом paths в качестве экспорта по умолчанию. Метод paths должен возвращать массив объектов со свойством params. Для каждого из этих объектов будет создана соответствующая страница.

Дан следующий массив paths:

js
// packages/[pkg].paths.js
export default {
  paths() {
    return [{ params: { pkg: 'foo' } }, { params: { pkg: 'bar' } }]
  }
}

Сгенерированные HTML-страницы будут выглядеть так:

.
└─ packages
   ├─ foo.html
   └─ bar.html

Несколько параметров

Динамический маршрут может содержать несколько параметров:

Структура файлов

.
└─ packages
   ├─ [pkg]-[version].md
   └─ [pkg]-[version].paths.js

Загрузчик путей

js
export default {
  paths: () => [
    { params: { pkg: 'foo', version: '1.0.0' } },
    { params: { pkg: 'foo', version: '2.0.0' } },
    { params: { pkg: 'bar', version: '1.0.0' } },
    { params: { pkg: 'bar', version: '2.0.0' } }
  ]
}

Результат

.
└─ packages
   ├─ foo-1.0.0.html
   ├─ foo-2.0.0.html
   ├─ bar-1.0.0.html
   └─ bar-2.0.0.html

Динамически генерируемые пути

Модуль загрузчика путей запускается в Node.js и выполняется только во время сборки. Вы можете динамически генерировать массив путей, используя любые данные, как локальные, так и удалённые.

Генерация путей из локальных файлов:

js
import fs from 'fs'

export default {
  paths() {
    return fs.readdirSync('packages').map((pkg) => {
      return { params: { pkg } }
    })
  }
}

Генерация путей из удалённых данных:

js
export default {
  async paths() {
    const pkgs = await (await fetch('https://my-api.com/packages')).json()

    return pkgs.map((pkg) => {
      return {
        params: {
          pkg: pkg.name,
          version: pkg.version
        }
      }
    })
  }
}

Доступ к параметрам на странице

Вы можете использовать параметры для передачи дополнительных данных на каждую страницу. Файл маршрута Markdown может получить доступ к параметрам текущей страницы в выражениях Vue через глобальное свойство $params:

md
- package name: {{ $params.pkg }}
- version: {{ $params.version }}

Вы также можете получить доступ к параметрам текущей страницы через Runtime API useData. Это доступно как в файлах Markdown, так и в компонентах Vue:

vue
<script setup>
import { useData } from 'vitepress'

// params — это ref-ссылка Vue
const { params } = useData()

console.log(params.value)
</script>

Рендеринг необработанного содержимого

Параметры, передаваемые странице, будут сериализованы в полезной нагрузке клиентского JavaScript, поэтому вам следует избегать передачи в параметрах больших объемов данных, например, необработанного Markdown или HTML-контента, полученного из удалённой CMS.

Вместо этого вы можете передавать такое содержимое на каждую страницу с помощью свойства content каждого объекта path:

js
export default {
  async paths() {
    const posts = await (await fetch('https://my-cms.com/blog-posts')).json()

    return posts.map((post) => {
      return {
        params: { id: post.id },
        content: post.content // необработанный Markdown или HTML
      }
    })
  }
}

Затем используйте следующий специальный синтаксис, чтобы отобразить содержимое как часть самого файла Markdown:

md
<!-- @content -->

Опубликовано под лицензией MIT.