> For AI agents: the complete documentation index is available at https://rspress.rs/zh/llms.txt, the full documentation bundle is available at https://rspress.rs/zh/llms-full.txt.

# 约定式路由

## 什么是约定式路由

Rspress 使用的是文件系统路由，页面的文件路径会简单地映射为路由路径，这样会让整个项目的路由非常直观。

例如，如果在 `docs` 目录中有一个名为 `foo.md` 的文件，则该文件的路由路径将是 `/foo`。

## 映射规则

Rspress 会自动扫描根目录和所有子目录，并将文件路径映射到路由路径。例如，如果你有以下的文件结构：

```tree
docs
├── foo
│   ├── bar.md
│   └── index.md
├── zoo.md
└── index.md
```

那么 `bar.md` 的路由路径会是 `/foo/bar`， `/foo/index.md` 的路由路径会是 `/foo/`。

具体映射规则如下：

| 文件路径            | 路由路径       | `cleanUrl: false` 路径 |
| --------------- | ---------- | -------------------- |
| `index.md`      | `/`        | `/index.html`        |
| `/zoo.md`       | `/zoo`     | `/zoo.html`          |
| `/foo/index.md` | `/foo/`    | `/foo/index.html`    |
| `/foo/bar.md`   | `/foo/bar` | `/foo/bar.html`      |

:::warning

不要出现文件与文件夹同名的情况，会造成路由冲突，例如下面的文件结构是不允许的：

```tree
docs
├── foo
│   └── index.md
└── foo.md
```

:::

## TSX 路由

在约定式路由中，除了 `.md(x)` 文件，还可以使用 `.tsx` 文件作为路由组件，在 `.tsx` 中默认导出一个组件，该组件会被自动注册到路由中。例如：

```tsx title="foo.tsx"
export default () => {
  return <div>foo</div>;
};
```

当然，如果你想要定制布局，可以添加一个导出，声明布局类型，例如：

```tsx title="foo.tsx"
export const frontmatter = {
  // 声明布局类型
  // 这里的 custom 布局中不会出现侧边栏
  pageType: 'custom',
};
```

各个 pageType 的含义详情请参考 [API 文档](https://rspress.rs/zh/api/config/config-frontmatter.md#pagetype)。

## 自定义行为

如果要自定义路由行为，可以使用配置文件中的 `route` 字段。例如：

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';

export default defineConfig({
  route: {
    // 这些文件会被注册为路由（支持 glob 模式）
    include: ['other-dir/**/*'],
    // 这些文件将不会被注册为路由（支持 glob 模式）
    exclude: ['components/**/*', 'fragments/**/*'],
  },
});
```

## 默认排除 `_` 开头的文件

在 [docs 目录](https://rspress.rs/zh/api/config/config-basic.md#root) 中，使用 MDX 片段或 React 组件要通过 [route.exclude](https://rspress.rs/zh/api/config/config-basic.md#routeexclude) 配置从路由中排除。为方便使用，我们约定以 "\_" 开头的文件会被 [route.excludeConvention](https://rspress.rs/zh/api/config/config-basic.md#routeexcludeconvention) 默认排除。

你也可以将组件放到 docs 目录以外的相邻目录，例如：

```tree
docs
├── _button.mdx
└── index.mdx
components
└── button.tsx
```


**docs/index.mdx**

```mdx
import ButtonFragment from './_button.mdx';
import Button from '../../components/button';

<ButtonFragment />
<Button />
```


**docs/_button.mdx**

```mdx file="./_button.mdx"
#### button

这是一段来自 MDX 的文本

```


**components/button.tsx**

```tsx
const Button = () => <button>这是来自 tsx 的按钮</button>;
export default Button;
```


它将被渲染为：


#### button

这是一段来自 MDX 的文本
这是来自 tsx 的按钮

## 最佳实践

我们推荐你将文档文件放在 `docs` 目录下，这样可以让你的项目更加清晰。而对于非文档内容，比如自定义组件、工具函数等，可以放到 `docs` 目录之外进行维护，如果放到 `docs` 目录，需要配合 `route.excludes` 使用。

:::tip

如果要将自定义组件、文档片段放在 `docs` 目录，需要配合 `route.excludes` 使用，否则这些文件会被自动注册为路由，可能会导致一些意外的问题。

:::

以下是一种文件结构的最佳实践，包含了 [MDX 片段](https://rspress.rs/zh/guide/use-mdx/components.md#fragments)、[自定义主题](https://rspress.rs/zh/guide/basic/custom-theme.md)、[约定式路由](https://rspress.rs/zh/guide/basic/conventional-route.md)、[国际化](https://rspress.rs/zh/guide/basic/i18n.md)：

```tree
├── docs
│   ├── components  # 用于放置文档中使用到的 React 组件
│   │   └── Example.tsx
│   ├── zh
│   │   ├── fragments   # 用于放置一些 zh 的文档片段
│   │   │   └── example.mdx
│   │   └── index.mdx
│   └── en
│       ├── fragments   # 用于放置一些 en 的文档片段
│       │   └── example.mdx
│       └── index.mdx
└── theme
    ├── components # 用于放置主题相关的 React 组件
    │   └── DocFooter.tsx
    └── index.tsx
```

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';

export default defineConfig({
  route: {
    exclude: ['*/components/**/*', '*/fragments/**/*'], // 这些目录下的文件不会被注册为路由
  },
  lang: 'en',
  locales: [
    {
      lang: 'zh',
      label: '中文',
    },
    {
      lang: 'en',
      label: 'English',
    },
  ],
});
```

```json title="tsconfig.json"
{
  "compilerOptions": {
    "lib": ["DOM", "ESNext"],
    "jsx": "react-jsx",
    "moduleResolution": "bundler",
    "paths": {
      "i18n": ["./i18n.json"],
      "@theme": ["./theme/index.tsx"]
    }
  },
  "include": ["docs", "theme", "rspress.config.ts"],
  "mdx": {
    "checkMdx": true
  }
}
```
