路由
Docusaurus 的路由系統遵循單一頁面應用程式慣例:一個路由,一個元件。在本節中,我們將從說明三個內容外掛程式(文件、網誌和頁面)中的路由開始,然後再深入探討底層路由系統。
內容外掛程式中的路由
每個內容外掛程式都提供一個 routeBasePath
選項。它定義外掛程式將其路由附加到的位置。預設情況下,文件外掛程式將其路由放在 /docs
下;網誌外掛程式,/blog
;頁面外掛程式,/
。您可以這樣思考路由結構
任何路由都將與此巢狀路由組態進行比對,直到找到正確比對為止。例如,在給定路由 /docs/configuration
時,Docusaurus 會先進入 /docs
分支,然後在文件外掛程式建立的子路由中搜尋。
變更 routeBasePath
可以有效地改變網站的路由結構。例如,在 僅文件模式 中,我們提到對文件設定 routeBasePath: '/'
表示文件外掛程式建立的所有路由都不會具有 /docs
字首,但它並不會阻止其他外掛程式建立更多子路由,例如 /blog
。
接著,我們來看看三個外掛程式如何建構它們自己的「子路由盒子」。
頁面路由
頁面路由非常直接:檔案路徑會直接對應到 URL,沒有其他自訂方式。如需更多資訊,請參閱 頁面文件。
用於標記頁面的元件是 @theme/MDXPage
。React 頁面會直接作為路由的元件使用。
部落格路由
部落格會建立下列路由
- 文章清單頁面:
/
、/page/2
、/page/3
...- 可以透過
pageBasePath
選項自訂路由。 - 元件是
@theme/BlogListPage
。
- 可以透過
- 文章頁面:
/2021/11/21/algolia-docsearch-migration
、/2021/05/12/announcing-docusaurus-two-beta
...- 從每篇文章標記中產生。
- 可以透過
slug
名詞解釋完全自訂路由。 - 元件是
@theme/BlogPostPage
。
- 標籤清單頁面:
/tags
- 可以透過
tagsBasePath
選項自訂路由。 - 元件是
@theme/BlogTagsListPage
。
- 可以透過
- 標籤頁面:
/tags/adoption
、/tags/beta
...- 從每篇文章的名詞解釋中定義標籤並產生。
- 路由始終具有
tagsBasePath
中定義的基礎,但可以透過標籤的permalink
欄位自訂子路由。 - 元件是
@theme/BlogTagsPostsPage
。
- 檔案頁面:
/archive
- 可以透過
archiveBasePath
選項自訂路由。 - 元件是
@theme/BlogArchivePage
。
- 可以透過
文件路由
文件是唯一會建立 巢狀路由 的外掛程式。在最上方,它會註冊 版本路徑:/
、/next
、/2.0.0-beta.13
...提供版本內容,包括配置和側欄。這可確保在個別文件之間切換時,側欄的狀態會保留,同時也能透過導覽列下拉式選單切換版本,並停留在同一個文件。使用的元件是 @theme/DocPage
。
個別文件會在導覽列、頁尾、側邊欄等由 DocPage
元件提供後,將顯示在剩餘空間中。例如,這個頁面 /docs/advanced/routing
是從 ./versioned_docs/version-3.5.2/advanced/routing.md
中的檔案所產生。使用的元件是 @theme/DocItem
。
文件的 slug
前置設定會自訂路徑的最後一部分,但是基礎路徑總是會由外掛程式的 routeBasePath
和版本的 path
所定義。
檔案路徑和 URL 路徑
在文件當中,我們總是會試著明確說明我們是在討論檔案路徑還是 URL 路徑。內容外掛程式通常會直接將檔案路徑對應到 URL 路徑,例如 ./docs/advanced/routing.md
會變成 /docs/advanced/routing
。但是,使用 slug
時,可以讓 URL 完全與檔案結構脫鉤。
在 Markdown 撰寫連結時,可以表示的是檔案路徑,或URL 路徑,Docusaurus 會使用許多啟發法來決定。
- 如果路徑有
@site
開頭,永遠會是資源檔案路徑。 - 如果路徑有
http(s)://
開頭,永遠會是 URL 路徑。 - 如果路徑沒有副檔名,會是 URL 路徑。例如,一個連結
[page](../plugins)
在一個 URL 為/docs/advanced/routing
的頁面上,會連結到/docs/plugins
。Docusaurus 只會在建置你的網站時偵測到破碎的連結(當它知道完整的路徑結構時),但是不會對檔案的存在做出任何預設。這和在 JSX 檔案中撰寫<a href="../plugins">page</a>
完全一樣。 - 如果路徑有
.md(x)
副檔名,Docusaurus 會嘗試將這個 Markdown 檔案解析成 URL,並將檔案路徑替換成 URL 路徑。 - 如果路徑有其他副檔名,Docusaurus 會將其視為 資源 並將其組合。
下列目錄結構可以幫助你視覺化此檔案 → URL 對應。假設任一頁面都沒有自訂 slug。
範例網站結構
.
├── blog # blog plugin has routeBasePath: '/blog'
│ ├── 2019-05-28-first-blog-post.md # -> /blog/2019/05/28/first-blog-post
│ ├── 2019-05-29-long-blog-post.md # -> /blog/2019/05/29/long-blog-post
│ ├── 2021-08-01-mdx-blog-post.mdx # -> /blog/2021/08/01/mdx-blog-post
│ └── 2021-08-26-welcome
│ ├── docusaurus-plushie-banner.jpeg
│ └── index.md # -> /blog/2021/08/26/welcome
├── docs # docs plugin has routeBasePath: '/docs'; current version has base path '/'
│ ├── intro.md # -> /docs/intro
│ ├── tutorial-basics
│ │ ├── _category_.json
│ │ ├── congratulations.md # -> /docs/tutorial-basics/congratulations
│ │ └── markdown-features.mdx # -> /docs/tutorial-basics/markdown-features
│ └── tutorial-extras
│ ├── _category_.json
│ ├── manage-docs-versions.md # -> /docs/tutorial-extras/manage-docs-versions
│ └── translate-your-site.md # -> /docs/tutorial-extras/translate-your-site
├── src
│ └── pages # pages plugin has routeBasePath: '/'
│ ├── index.module.css
│ ├── index.tsx # -> /
│ └── markdown-page.md # -> /markdown-page
└── versioned_docs
└── version-1.0.0 # version has base path '/1.0.0'
├── intro.md # -> /docs/1.0.0/intro
├── tutorial-basics
│ ├── _category_.json
│ ├── congratulations.md # -> /docs/1.0.0/tutorial-basics/congratulations
│ └── markdown-features.mdx # -> /docs/1.0.0/tutorial-basics/markdown-features
└── tutorial-extras
├── _category_.json
├── manage-docs-versions.md # -> /docs/1.0.0/tutorial-extras/manage-docs-versions
└── translate-your-site.md # -> /docs/1.0.0/tutorial-extras/translate-your-site
關於內容外掛程式只需了解這麼多。讓我們退後一步,聊聊 Docusaurus 應用程式中路由一班是如何運作的。
路徑會變成 HTML 檔案
由於 Docusaurus 是一個伺服器端渲染架構,所以產生出來的所有路由都會被伺服器端渲染成靜態 HTML 檔案。如果您熟悉像 Apache2 這種 HTTP 伺服器的行為,您將會理解它如何完成:當瀏覽器傳送請求到路由 /docs/advanced/routing
,伺服器會將其解譯為對 HTML 檔案 /docs/advanced/routing/index.html
的請求,然後傳回它。
/docs/advanced/routing
路由可以對應到 /docs/advanced/routing/index.html
或 /docs/advanced/routing.html
。一些託管供應商使用尾部斜線來區分它們,並且可能容忍或不容忍另一個。進一步在 尾部斜線指南 閱讀更多內容。
舉例來說,上面目錄的建置輸出 (忽略其他資源和 JS 捆綁包) 是
上面工作區的輸出
build
├── 404.html # /404/
├── blog
│ ├── archive
│ │ └── index.html # /blog/archive/
│ ├── first-blog-post
│ │ └── index.html # /blog/first-blog-post/
│ ├── index.html # /blog/
│ ├── long-blog-post
│ │ └── index.html # /blog/long-blog-post/
│ ├── mdx-blog-post
│ │ └── index.html # /blog/mdx-blog-post/
│ ├── tags
│ │ ├── docusaurus
│ │ │ └── index.html # /blog/tags/docusaurus/
│ │ ├── hola
│ │ │ └── index.html # /blog/tags/hola/
│ │ └── index.html # /blog/tags/
│ └── welcome
│ └── index.html # /blog/welcome/
├── docs
│ ├── 1.0.0
│ │ ├── intro
│ │ │ └── index.html # /docs/1.0.0/intro/
│ │ ├── tutorial-basics
│ │ │ ├── congratulations
│ │ │ │ └── index.html # /docs/1.0.0/tutorial-basics/congratulations/
│ │ │ └── markdown-features
│ │ │ └── index.html # /docs/1.0.0/tutorial-basics/markdown-features/
│ │ └── tutorial-extras
│ │ ├── manage-docs-versions
│ │ │ └── index.html # /docs/1.0.0/tutorial-extras/manage-docs-versions/
│ │ └── translate-your-site
│ │ └── index.html # /docs/1.0.0/tutorial-extras/translate-your-site/
│ ├── intro
│ │ └── index.html # /docs/1.0.0/intro/
│ ├── tutorial-basics
│ │ ├── congratulations
│ │ │ └── index.html # /docs/tutorial-basics/congratulations/
│ │ └── markdown-features
│ │ └── index.html # /docs/tutorial-basics/markdown-features/
│ └── tutorial-extras
│ ├── manage-docs-versions
│ │ └── index.html # /docs/tutorial-extras/manage-docs-versions/
│ └── translate-your-site
│ └── index.html # /docs/tutorial-extras/translate-your-site/
├── index.html # /
└── markdown-page
└── index.html # /markdown-page/
如果 trailingSlash
設為 false
,建置將發出 intro.html
而不是 intro/index.html
。
所有 HTML 檔案都將使用絕對網址來參照其 JS 資源,因此為了定位正確的資源,您必須設定 baseUrl
欄位。請注意,baseUrl
沒有影響發出的捆綁包的檔案結構:基底網址在 Docusaurus 路由系統的上方一層。您可以將 url
和 baseUrl
的總和視為您的 Docusaurus 網站的實際位置。
舉例來說,發出的 HTML 將包含類似於 <link rel="preload" href="/assets/js/runtime~main.7ed5108a.js" as="script">
的連結。由於絕對網址會從主機解析,如果捆綁包放置在路徑 https://example.com/base/
下,連結將指向 https://example.com/assets/js/runtime~main.7ed5108a.js
,而這,嗯,是不存在的。透過指定 /base/
作為基底網址,連結將正確指向 /base/assets/js/runtime~main.7ed5108a.js
。
已本地域化的網站的基底網址中也有地區設定。比如說,https://docusaurus.dev.org.tw/zh-CN/docs/advanced/routing/
的基底網址為 /zh-CN/
。
產生與取用路由
addRoute
生命週期動作用於產生路由。它將一段路由設定註冊到路由樹,提供路由、元件以及元件所需的屬性。屬性與元件都提供給打包器作為 require
的路徑,因為如 架構概觀 中所解釋的,伺服器與用戶端僅透過暫存檔進行通訊。
所有路由都彙集在 .docusaurus/routes.js
中,您可以使用 debug 外掛的 路由面板 來檢視。
在客戶端上我們提供 @docusaurus/router
以存取頁面的路由。@docusaurus/router
是 react-router-dom
套件的再匯出。範例來說,你可以使用 useLocation
來取得目前頁面的 位置,並使用 useHistory
來存取 歷程物件。(它們與瀏覽器 API 不同,但功能很類似。請參考 React Router 文件以取得特定 API。)
這個 API 是SSR 安全的,這與僅限瀏覽器的 window.location
不同。
import React from 'react';
import {useLocation} from '@docusaurus/router';
export function PageRoute() {
// React router provides the current component's route, even in SSR
const location = useLocation();
return (
<span>
We are currently on <code>{location.pathname}</code>
</span>
);
}
/docs/advanced/routing
從 SPA 重新導向中逸出
Docusaurus 建立單一頁面應用程式,路由轉換是透過 React 的 history.push()
方法進行。這項操作是在客戶端上進行的。但要以這種方式進行路由轉換的前提是該目標網址為我們的路由所知曉。否則,路由會擷取此路徑,並顯示 404 網頁。
如果你把一些 HTML 頁面放在 static
資料夾裡,這些頁面將會複製到建置結果中,因此可以作為網站的一部分存取,但這並不是 Docusaurus 路由系統的一部分。我們提供一個 pathname://
協定,這可以讓你以非 SPA 的方式重新導向到你的網域的另一個部分,就如同這個路由是一個外部連結一樣。
- [pathname:///pure-html](pathname:///pure-html)
pathname://
協定可用於參考靜態資料夾中的任何內容。例如,Docusaurus 會把 所有 Markdown 靜態資源轉換成 require() 呼叫。你可以使用 pathname://
來讓它保持一般的連結,而不是被 webpack 影像化。

[An asset from the static](pathname:///files/asset.pdf)
Docusaurus 只會移除 pathname://
前綴,而不會處理內容。