跳到內容

路由

基於檔案的路由

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 devvitepress build 時,VitePress 會使用目前的作業目錄作為專案根目錄。若要指定子目錄作為根目錄,你必須將相對路徑傳遞給命令。例如,如果你的 VitePress 專案位於 ./docs,你應該執行 vitepress dev docs

.
├─ docs                    # project root
│  ├─ .vitepress           # config dir
│  ├─ getting-started.md
│  └─ index.md
└─ ...
sh
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。

md
<!-- 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(在新分頁中開啟)或明確指定目標

輸入

md
[Link to pure.html](/pure.html){target="_self"}

輸出

連結到 pure.html

註解

在 Markdown 連結中,base 會自動加到 URL 前面。這表示如果您想連結到基礎目錄以外的頁面,您需要在連結中使用類似 ../../pure.html 的內容(由瀏覽器相對於目前頁面解析)。

或者,您可以直接使用錨點標籤語法

md
<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 選項來達成,像這樣

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
[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 陣列

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 路由檔案可以使用 $params 全域屬性透過 Vue 表達式存取目前的頁面參數

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

你也可以透過 useData 執行時期 API 存取目前的頁面參數。這在 Markdown 檔案和 Vue 元件中都可用

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 屬性將此類內容傳遞到每個頁面

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 // raw Markdown or HTML
      }
    })
  }
}

然後,使用以下特殊語法將內容作為 Markdown 檔案本身的一部分呈現

md
<!-- @content -->

在 MIT 授權條款下釋出。