路由
基于文件的路由
VitePress使用基于文件的路由,这意味着生成的HTML页面是从源Markdown文件的目录结构映射的。例如,给定以下目录结构:
.
├─ guide
│ ├─ getting-started.md
│ └─ index.md
├─ index.md
└─ prologue.md生成的HTML页面将是:
index.md --> /index.html (accessible as /)
prologue.md --> /prologue.html
guide/index.md --> /guide/index.html (accessible as /guide/)
guide/getting-started.md --> /guide/getting-started.html生成的HTML可以托管在任何可以提供静态文件的web服务器上。
根目录和源目录
在VitePress项目的文件结构中有两个重要的概念:项目根目录和源目录。
项目根目录
项目根目录是VitePress尝试寻找. VitePress这个特殊目录的地方。. VitePress目录是VitePress配置文件、开发服务器缓存、构建输出和可选主题定制代码的保留位置。
当您从命令行运行vitepress dev或vitepress build时,vitepress将使用当前工作目录作为项目根目录。要将子目录指定为根目录,需要将相对路径传递给该命令。例如,如果你的VitePress项目位于./docs中,你应该运行VitePress dev docs:
.
├─ docs # project root
│ ├─ .vitepress # config dir
│ ├─ getting-started.md
│ └─ index.md
└─ ...vitepress dev docs这将导致以下source-to-HTML映射:
docs/index.md --> /index.html (accessible as /)
docs/getting-started.md --> /getting-started.html源目录
源目录是Markdown源文件所在的位置。默认情况下,它与项目根目录相同。但是,您可以通过srcDir配置选项对其进行配置。
srcDir选项是相对于项目根目录进行解析的。例如,使用srcDir: 'src',你的文件结构将是这样的:
. # project root
├─ .vitepress # config dir
└─ src # source dir
├─ getting-started.md
└─ index.md由此产生source-to-HTML的映射:
src/index.md --> /index.html (accessible as /)
src/getting-started.md --> /getting-started.html页面间链接
在页面之间链接时,可以使用绝对路径和相对路径。请注意,虽然.md和.html扩展名都可以工作,但最好的做法是省略文件扩展名,以便VitePress可以根据您的配置生成最终的url。
<!-- Do -->
[Getting Started](./getting-started)
[Getting Started](../guide/getting-started)
<!-- Don't -->
[Getting Started](./getting-started.md)
[Getting Started](./getting-started.html)有关链接到资产(如图像)的更多信息,请参见资产处理。
生成干净的URL
Server Support Required
To serve clean URLs with VitePress, server-side support is required.
默认情况下,VitePress将入站链接解析为以.html结尾的url。然而,一些用户可能更喜欢“干净的url”,不带。html扩展名——例如,example.com/path而不是example.com/path.html。
一些服务器或托管平台(例如Netlify或Vercel)提供了将/foo这样的URL映射到/foo.html(如果存在的话)的能力,而不需要重定向:
Netlify默认支持此功能。Vercel需要在Vercel .json中启用cleanUrls选项。
如果这个功能对你可用,你也可以启用VitePress自己的cleanUrls配置选项,这样:
- 页面之间的入站链接是在没有
.html扩展名的情况下生成的。 - 如果当前路径以
.html结尾,路由器将执行客户端重定向到无扩展名路径。
然而,如果你不能配置你的服务器这样的支持(例如GitHub页面),你将不得不手动求助于以下目录结构:
.
├─ getting-started
│ └─ index.md
├─ installation
│ └─ index.md
└─ index.md路由重写
您可以自定义源目录结构和生成的页面之间的映射。当你有一个复杂的项目结构时,它很有用。例如,假设你有一个带有多个包的monorepo,并且希望像这样将文档与源文件一起放置:
.
├─ 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选项来实现:
export default {
rewrites: {
'packages/:pkg/src/(.*)': ':pkg/index.md'
}
}重写路径是使用path-to-regexp包编译的——要了解更高级的语法,请参阅其文档。
Relative Links with Rewrites
When rewrites are enabled, relative links should be based on the rewritten paths. For example, in order to create a relative link from packages/pkg-a/src/pkg-a-code.md to packages/pkg-b/src/pkg-b-code.md, you should use:
[Link to PKG B](../pkg-b/pkg-b-code)动态路由
您可以使用单个Markdown文件和动态数据生成多个页面。例如,创建“packages/[pkg]”.Md文件,为项目中的每个包生成相应的页面。这里,[pkg]段是一个路由参数,用于将每个页面与其他页面区分开来。
路径加载文件
由于VitePress是一个静态站点生成器,因此必须在构建时确定可能的页面路径。因此,动态路由页面必须伴随着路径加载器文件。packages/[pkg].md,我们需要packages/[pkg].paths.js(.ts也支持):
.
└─ packages
├─ [pkg].md # route template
└─ [pkg].paths.js # route paths loader路径加载器应该提供一个具有paths方法的对象作为其默认导出。paths方法应该返回一个带有params属性的对象数组。每个对象都将生成一个相应的页面。
给定以下路径数组:
// 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路径加载器
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中运行,只在构建时执行。您可以使用本地或远程的任何数据动态生成路径数组。
从本地文件生成路径:
import fs from 'fs'
export default {
paths() {
return fs
.readdirSync('packages')
.map((pkg) => {
return { params: { pkg }}
})
}
}从远程数据生成路径:
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路由文件可以通过$params全局属性访问Vue表达式中的当前页面参数:
- package name: {{ $params.pkg }}
- version: {{ $params.version }}你也可以通过[useData](../reference/runtime- API # useData)运行时API访问当前页面的参数。这在Markdown文件和Vue组件中都可用:
<script setup>
import { useData } from 'vitepress'
// params is a Vue ref
const { params } = useData()
console.log(params.value)
</script>渲染原始内容
传递给页面的参数将在客户端JavaScript有效负载中序列化,因此应该避免在参数中传递大量数据,例如从远程CMS获取的原始Markdown或HTML内容。
相反,你可以使用每个路径对象上的content属性将这样的内容传递到每个页面:
export default {
paths() {
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 // raw Markdown or HTML
}
})
}
}
}然后,使用下面的特殊语法将内容呈现为Markdown文件本身的一部分:
<!-- @content -->