Skip to main content
Version: 3.6.1

路由

¥Routing

Docusaurus 的路由系统遵循单页应用约定:一条路由,一个组件。在本节中,我们将首先讨论三个内容插件(文档、博客和页面)内的路由,然后进一步讨论底层路由系统。

¥Docusaurus' routing system follows single-page application conventions: one route, one component. In this section, we will begin by talking about routing within the three content plugins (docs, blog, and pages), and then go beyond to talk about the underlying routing system.

内容插件中的路由

¥Routing in content plugins

每个内容插件都提供 routeBasePath 选项。它定义插件将其路由附加到的位置。默认情况下,docs 插件将其路由放在 /docs 下;博客插件,/blog;和页面插件,/。你可以这样考虑路由结构:

¥Every content plugin provides a routeBasePath option. It defines where the plugins append their routes to. By default, the docs plugin puts its routes under /docs; the blog plugin, /blog; and the pages plugin, /. You can think about the route structure like this:

任何路由都将与此嵌套路由配置进行匹配,直到找到良好的匹配为止。例如,当给定路由 /docs/configuration 时,Docusaurus 首先进入 /docs 分支,然后在 docs 插件创建的子路由中进行搜索。

¥Any route will be matched against this nested route config until a good match is found. For example, when given a route /docs/configuration, Docusaurus first enters the /docs branch, and then searches among the subroutes created by the docs plugin.

更改 routeBasePath 可以有效地改变站点的路由结构。例如,在 仅文档模式 中,我们提到为文档配置 routeBasePath: '/' 意味着文档插件创建的所有路由都不会具有 /docs 前缀,但这并不妨碍你拥有更多其他插件创建的子路由,例如 /blog

¥Changing routeBasePath can effectively alter your site's route structure. For example, in Docs-only mode, we mentioned that configuring routeBasePath: '/' for docs means that all routes that the docs plugin create would not have the /docs prefix, yet it doesn't prevent you from having more subroutes like /blog created by other plugins.

接下来我们看看这三个插件是如何构造自己的 "子路由盒".5 的。

¥Next, let's look at how the three plugins structure their own "boxes of subroutes".

页面路由

¥Pages routing

页面路由很简单:文件路径直接映射到 URL,无需任何其他方式进行自定义。请参阅 页面文档 了解更多信息。

¥Pages routing are straightforward: the file paths directly map to URLs, without any other way to customize. See the pages docs for more information.

Markdown 页面使用的组件是 @theme/MDXPage。React 页面直接用作路由的组件。

¥The component used for Markdown pages is @theme/MDXPage. React pages are directly used as the route's component.

博客路由

¥Blog routing

该博客创建了以下路由:

¥The blog creates the following routes:

  • 帖子列表页面://page/2/page/3...

    ¥Posts list pages: /, /page/2, /page/3...

    • 该路由可通过 pageBasePath 选项进行自定义。

      ¥The route is customizable through the pageBasePath option.

    • 该组件是 @theme/BlogListPage

      ¥The component is @theme/BlogListPage.

  • 帖子页面:/2021/11/21/algolia-docsearch-migration/2021/05/12/announcing-docusaurus-two-beta……

    ¥Post pages: /2021/11/21/algolia-docsearch-migration, /2021/05/12/announcing-docusaurus-two-beta...

    • 从每个 Markdown 帖子生成。

      ¥Generated from each Markdown post.

    • 路由可通过 slug 前端完全定制。

      ¥The routes are fully customizable through the slug front matter.

    • 该组件是 @theme/BlogPostPage

      ¥The component is @theme/BlogPostPage.

  • 标签列表页面:/tags

    ¥Tags list page: /tags

    • 该路由可通过 tagsBasePath 选项进行自定义。

      ¥The route is customizable through the tagsBasePath option.

    • 该组件是 @theme/BlogTagsListPage

      ¥The component is @theme/BlogTagsListPage.

  • 标签页:/tags/adoption/tags/beta……

    ¥Tag pages: /tags/adoption, /tags/beta...

    • 通过每个帖子的前文中定义的标签生成。

      ¥Generated through the tags defined in each post's front matter.

    • 路由始终具有在 tagsBasePath 中定义的基础,但子路由可通过标签的 permalink 字段进行自定义。

      ¥The routes always have base defined in tagsBasePath, but the subroutes are customizable through the tag's permalink field.

    • 该组件是 @theme/BlogTagsPostsPage

      ¥The component is @theme/BlogTagsPostsPage.

  • 存档页面:/archive

    ¥Archive page: /archive

    • 该路由可通过 archiveBasePath 选项进行自定义。

      ¥The route is customizable through the archiveBasePath option.

    • 该组件是 @theme/BlogArchivePage

      ¥The component is @theme/BlogArchivePage.

文档路由

¥Docs routing

该文档是唯一创建嵌套路由的插件。在顶部,它注册了 版本路径//next/2.0.0-beta.13...它提供版本上下文,包括布局和侧边栏。这确保了在各个文档之间切换时,侧边栏的状态得以保留,并且你可以通过导航栏下拉列表在版本之间切换,同时保持在同一文档上。使用的组件是 @theme/DocPage

¥The docs is the only plugin that creates nested routes. At the top, it registers version paths: /, /next, /2.0.0-beta.13... which provide the version context, including the layout and sidebar. This ensures that when switching between individual docs, the sidebar's state is preserved, and that you can switch between versions through the navbar dropdown while staying on the same doc. The component used is @theme/DocPage.

导航栏、页脚、侧边栏等均由 DocPage 组件提供后,各个文档将在剩余空间中渲染。例如,此页面 /docs/advanced/routing 是从 ./versioned_docs/version-3.6.1/advanced/routing.md 处的文件生成的。使用的组件是 @theme/DocItem

¥The individual docs are rendered in the remaining space after the navbar, footer, sidebar, etc. have all been provided by the DocPage component. For example, this page, /docs/advanced/routing, is generated from the file at ./versioned_docs/version-3.6.1/advanced/routing.md. The component used is @theme/DocItem.

文档的 slug 前面的内容自定义了路由的最后一部分,但基本路由始终由插件的 routeBasePath 和版本的 path 定义。

¥The doc's slug front matter customizes the last part of the route, but the base route is always defined by the plugin's routeBasePath and the version's path.

文件路径和 URL 路径

¥File paths and URL paths

在整个文档中,我们总是尽量明确我们是在谈论文件路径还是 URL 路径。内容插件通常将文件路径直接映射到 URL 路径,例如 ./docs/advanced/routing.md 将变成 /docs/advanced/routing。但是,使用 slug,你可以使 URL 与文件结构完全解耦。

¥Throughout the documentation, we always try to be unambiguous about whether we are talking about file paths or URL paths. Content plugins usually map file paths directly to URL paths, for example, ./docs/advanced/routing.md will become /docs/advanced/routing. However, with slug, you can make URLs totally decoupled from the file structure.

在 Markdown 中编写链接时,你可以指文件路径,也可以指 URL 路径,Docusaurus 将使用多种启发式方法来确定。

¥When writing links in Markdown, you could either mean a file path, or a URL path, which Docusaurus would use several heuristics to determine.

  • 如果路径具有 @site 前缀,则它始终是资源文件路径。

    ¥If the path has a @site prefix, it is always an asset file path.

  • 如果路径有 http(s):// 前缀,则它始终是 URL 路径。

    ¥If the path has an http(s):// prefix, it is always a URL path.

  • 如果路径没有扩展名,则它是 URL 路径。例如,URL /docs/advanced/routing 的页面上的链接 [page](../plugins) 将链接到 /docs/plugins。Docusaurus 仅在构建站点时(当它知道完整的路由结构时)检测损坏的链接,但不会对文件的存在做出任何假设。与在 JSX 文件中写入 <a href="../plugins">page</a> 完全相同。

    ¥If the path doesn't have an extension, it is a URL path. For example, a link [page](../plugins) on a page with URL /docs/advanced/routing will link to /docs/plugins. Docusaurus will only detect broken links when building your site (when it knows the full route structure), but will make no assumptions about the existence of a file. It is exactly equivalent to writing <a href="../plugins">page</a> in a JSX file.

  • 如果路径具有 .md(x) 扩展名,Docusaurus 会尝试将该 Markdown 文件解析为 URL,并用 URL 路径替换文件路径。

    ¥If the path has an .md(x) extension, Docusaurus would try to resolve that Markdown file to a URL, and replace the file path with a URL path.

  • 如果该路径有任何其他扩展名,Docusaurus 会将其视为 一项资源 并将其打包。

    ¥If the path has any other extension, Docusaurus would treat it as an asset and bundle it.

以下目录结构可以帮助你可视化此文件 → URL 映射。假设任何页面中都没有 slug 自定义。

¥The following directory structure may help you visualize this file → URL mapping. Assume that there's no slug customization in any page.

A sample site structure
.
├── 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 应用中路由的一般工作原理。

¥So much about content plugins. Let's take one step back and talk about how routing works in a Docusaurus app in general.

路由变成 HTML 文件

¥Routes become HTML files

由于 Docusaurus 是一个服务器端渲染框架,因此生成的所有路由都将在服务器端渲染为静态 HTML 文件。如果你熟悉像 Apache2 这样的 HTTP 服务器的行为,你就会明白这是如何完成的:当浏览器向路由 /docs/advanced/routing 发送请求时,服务器将其解释为对 HTML 文件 /docs/advanced/routing/index.html 的请求,并返回该请求。

¥Because Docusaurus is a server-side rendering framework, all routes generated will be server-side rendered into static HTML files. If you are familiar with the behavior of HTTP servers like Apache2, you will understand how this is done: when the browser sends a request to the route /docs/advanced/routing, the server interprets that as request for the HTML file /docs/advanced/routing/index.html, and returns that.

/docs/advanced/routing 路由可以对应于 /docs/advanced/routing/index.html/docs/advanced/routing.html。一些托管提供商使用尾部斜杠的存在来区分它们,并且可能会也可能不会容忍另一个。请阅读 尾部斜线引导 中的更多内容。

¥The /docs/advanced/routing route can correspond to either /docs/advanced/routing/index.html or /docs/advanced/routing.html. Some hosting providers differentiate between them using the presence of a trailing slash, and may or may not tolerate the other. Read more in the trailing slash guide.

例如,上面目录的构建输出是(忽略其他资源和 JS 包):

¥For example, the build output of the directory above is (ignoring other assets and JS bundle):

Output of the above workspace
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

¥If trailingSlash is set to false, the build would emit intro.html instead of intro/index.html.

所有 HTML 文件都将使用绝对 URL 引用其 JS 资源,因此为了找到正确的资源,你必须配置 baseUrl 字段。请注意,baseUrl 不会影响触发的包的文件结构:基本 URL 比 Docusaurus 路由系统高一级。你可以将 urlbaseUrl 的聚合视为 Docusaurus 站点的实际位置。

¥All HTML files will reference its JS assets using absolute URLs, so in order for the correct assets to be located, you have to configure the baseUrl field. Note that baseUrl doesn't affect the emitted bundle's file structure: the base URL is one level above the Docusaurus routing system. You can see the aggregate of url and baseUrl as the actual location of your Docusaurus site.

例如,触发的 HTML 将包含类似 <link rel="preload" href="/assets/js/runtime~main.7ed5108a.js" as="script"> 的链接。因为绝对 URL 是从主机解析的,所以如果打包包放置在路径 https://example.com/base/ 下,则链接将指向 https://example.com/assets/js/runtime~main.7ed5108a.js,而 https://example.com/assets/js/runtime~main.7ed5108a.js 是不存在的。通过指定 /base/ 作为基本 URL,链接将正确指向 /base/assets/js/runtime~main.7ed5108a.js

¥For example, the emitted HTML would contain links like <link rel="preload" href="/assets/js/runtime~main.7ed5108a.js" as="script">. Because absolute URLs are resolved from the host, if the bundle placed under the path https://example.com/base/, the link will point to https://example.com/assets/js/runtime~main.7ed5108a.js, which is, well, non-existent. By specifying /base/ as base URL, the link will correctly point to /base/assets/js/runtime~main.7ed5108a.js.

本地化网站也将区域设置作为基本 URL 的一部分。例如,https://docusaurus.nodejs.cn/zh-CN/docs/advanced/routing/ 具有基本 URL /zh-CN/

¥Localized sites have the locale as part of the base URL as well. For example, https://docusaurus.nodejs.cn/zh-CN/docs/advanced/routing/ has base URL /zh-CN/.

生成和访问路由

¥Generating and accessing routes

addRoute 生命周期操作用于生成路由。它将一段路由配置注册到路由树中,给出一条路由、一个组件以及组件需要的 props。props 和组件都作为打包器到 require 的路径提供,因为如 架构概述 中所述,服务器和客户端仅通过临时文件进行通信。

¥The addRoute lifecycle action is used to generate routes. It registers a piece of route config to the route tree, giving a route, a component, and props that the component needs. The props and the component are both provided as paths for the bundler to require, because as explained in the architecture overview, server and client only communicate through temp files.

所有路由都聚合在 .docusaurus/routes.js 中,你可以使用调试插件的 路由面板 查看。

¥All routes are aggregated in .docusaurus/routes.js, which you can view with the debug plugin's routes panel.

在客户端,我们提供 @docusaurus/router 来访问页面的路由。@docusaurus/routerreact-router-dom 包的重新导出。例如,你可以使用 useLocation 来获取当前页面的 location,使用 useHistory 来获取当前页面的 历史对象。(它们与浏览器 API 不同,尽管功能相似。有关特定 API,请参阅 React Router 文档。)

¥On the client side, we offer @docusaurus/router to access the page's route. @docusaurus/router is a re-export of the react-router-dom package. For example, you can use useLocation to get the current page's location, and useHistory to access the history object. (They are not the same as the browser API, although similar in functionality. Refer to the React Router documentation for specific APIs.)

该 API 是 SSR 安全的,与仅浏览器的 window.location 不同。

¥This API is SSR safe, as opposed to the browser-only window.location.

myComponent.js
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>
);
}
http://localhost:3000
We are currently on /docs/advanced/routing

转义 SPA 重定向

¥Escaping from SPA redirects

Docusaurus 构建了一个 单页应用,其中路由转换是通过 React 路由的 history.push() 方法完成的。这个操作是在客户端完成的。然而,以这种方式进行路由转换的先决条件是我们的路由知道目标 URL。否则,路由会捕获此路径并显示 404 页面。

¥Docusaurus builds a single-page application, where route transitions are done through the history.push() method of React router. This operation is done on the client side. However, the prerequisite for a route transition to happen this way is that the target URL is known to our router. Otherwise, the router catches this path and displays a 404 page instead.

如果你将一些 HTML 页面放在 static 文件夹下,它们将被复制到构建输出,因此可以作为你网站的一部分进行访问,但它不是 Docusaurus 路由系统的一部分。我们提供 pathname:// 协议,允许你以非 SPA 方式重定向到域的另一部分,就好像此路由是外部链接一样。

¥If you put some HTML pages under the static folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a pathname:// protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link.

- [pathname:///pure-html](pathname:///pure-html)
http://localhost:3000

pathname:// 协议对于引用静态文件夹中的任何内容非常有用。例如,Docusaurus 会转换 所有 Markdown 静态资源都需要调用 require()。你可以使用 pathname:// 使其保持常规链接,而不是由 Webpack 进行哈希处理。

¥The pathname:// protocol is useful for referencing any content in the static folder. For example, Docusaurus would convert all Markdown static assets to require() calls. You can use pathname:// to keep it a regular link instead of being hashed by Webpack.

my-doc.md

![An image from the static](pathname:///img/docusaurus.png)



[An asset from the static](pathname:///files/asset.pdf)

Docusaurus 只会去除 pathname:// 前缀,而不处理内容。

¥Docusaurus will only strip the pathname:// prefix without processing the content.