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, кэша сервера разработки, выходных данных сборки и необязательного кода настройки темы.

Когда вы запускаете 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 base автоматически добавляется к URL. Это означает, что если вы хотите связать страницу за пределами вашей базы, вам нужно будет использовать что-то вроде ../../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 существует, без перенаправления:

  • Netlify и GitHub Pages поддерживают это по умолчанию.
  • Vercel требует включить эту опцию cleanUrls в vercel.json.

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

  • Входящие ссылки между страницами генерировались без расширения .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
- имя пакета: {{ $params.pkg }}
- версия: {{ $params.version }}

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

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

// params является Vue ref
const { params } = useData()

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

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

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

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

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