路由
基於檔案的路由
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 可以放置在任何可以提供靜態檔案的網路伺服器上。
根目錄和原始目錄
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
這將產生以下原始碼對應 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
產生的原始碼對應 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)
在 資產處理 中深入了解連結到資產(例如圖片)的資訊。
連結到非 VitePress 頁面
如果您想連結到網站中未由 VitePress 產生的頁面,您需要使用完整的 URL(在新分頁中開啟)或明確指定目標
輸入
[Link to pure.html](/pure.html){target="_self"}
輸出
註解
在 Markdown 連結中,base
會自動加到 URL 前面。這表示如果您想連結到基礎目錄以外的頁面,您需要在連結中使用類似 ../../pure.html
的內容(由瀏覽器相對於目前頁面解析)。
或者,您可以直接使用錨點標籤語法
<a href="/pure.html" target="_self">Link to pure.html</a>
產生乾淨的 URL
需要伺服器支援
要使用 VitePress 提供乾淨的 URL,需要伺服器端支援。
預設情況下,VitePress 會將內部連結解析為以 .html
結尾的 URL。但是,有些使用者可能偏好沒有 .html
副檔名的「乾淨 URL」- 例如,example.com/path
而不是 example.com/path.html
。
有些伺服器或託管平台(例如 Netlify、Vercel、GitHub Pages)提供將 URL 如 /foo
映射到 /foo.html
(如果存在)的功能,而不會重新導向
- Netlify 和 GitHub Pages 預設支援這項功能。
- Vercel 需要在
vercel.json
中啟用cleanUrls
選項。
如果您有這項功能,您也可以啟用 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
選項來達成,像這樣
// .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
選項也支援動態路由參數。在上面的範例中,如果您有許多套件,列出所有路徑會很冗長。由於它們都具有相同的檔案結構,您可以像這樣簡化設定
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
,您應該使用
[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
屬性的物件。這些物件中的每一個都會產生一個對應的頁面。
給定以下 paths
陣列
// 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
執行時期 API 存取目前的頁面參數。這在 Markdown 檔案和 Vue 元件中都可用
<script setup>
import { useData } from 'vitepress'
// params is a Vue ref
const { params } = useData()
console.log(params.value)
</script>
呈現原始內容
傳遞到頁面的參數會在用戶端 JavaScript payload 中序列化,因此你應該避免在參數中傳遞大量資料,例如從遠端 CMS 擷取的原始 Markdown 或 HTML 內容。
你可以使用每個路徑物件上的 content
屬性將此類內容傳遞到每個頁面
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 // raw Markdown or HTML
}
})
}
}
然後,使用以下特殊語法將內容作為 Markdown 檔案本身的一部分呈現
<!-- @content -->