> 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.

# 基础配置

## root

- **类型**： `string`
- **默认值**： `docs`

指定文档根目录。比如：

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

export default defineConfig({
  root: 'docs',
});
```

该配置同时支持相对路径和绝对路径，相对路径相对于当前工作目录。

当然，除了通过配置文件来指定文档根目录，你也可以通过命令行参数来指定，比如：

```bash
rspress dev docs
rspress build docs
```

## base

- **类型**： `string`
- **默认值**： `/`

部署基础路径。比如，如果你计划将你的站点部署到 `https://foo.github.io/bar/`，那么你应该将 `base` 设置为 `"/bar/"`：

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

export default defineConfig({
  base: '/bar/',
});
```

## siteOrigin


[新增于 v2.0.17](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.17)

- **类型**： `string`
- **默认值**： `""`

站点的可选部署 origin，例如 `https://foo.github.io`。

Rspress 在生成需要绝对 URL 的文件时会结合该值和 [`base`](#base)，例如 `llms.txt` 链接或插件输出。完整 URL 拼接顺序是 `siteOrigin + base + routePath`。

如果没有配置 `siteOrigin`，Rspress 会回退使用 `base + routePath`。

如果你的站点部署到 `https://foo.github.io/bar/`，请将 `siteOrigin` 设置为 `"https://foo.github.io"`，并将 `base` 设置为 `"/bar/"`：

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

export default defineConfig({
  siteOrigin: 'https://foo.github.io',
  base: '/bar/',
});
```

## title

- **类型**： `string`
- **默认值**： `"Rspress"`

站点标题。这个参数将被用作 HTML 页面的标题。例如：

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

export default defineConfig({
  title: '我的站点',
});
```

## description

- **类型**： `string`
- **默认值**： `""`

站点描述。这将用作 HTML 页面的描述。例如：

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

export default defineConfig({
  description: '我的站点描述',
});
```

## icon

- **类型**： `string | URL`
- **默认值**： `""`

站点图标。这个路径将用作 HTML 页面的图标路径。例如：

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

export default defineConfig({
  icon: '/favicon.ico',
});
```

对于普通路径，Rspress 会在 `public` 目录中找到你的图标，当然你也可以设置成一个 CDN 地址，或使用 `file://` 协议或 `URL` 来使用本地文件绝对路径。

## lang

- **类型**： `string`
- **默认值**： `"en"`

站点默认使用的语言。查看 [国际化](https://rspress.rs/zh/guide/basic/i18n.md) 了解更多。

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

export default defineConfig({
  lang: 'en',
  locales: [
    {
      lang: 'en',
      // ...
    },
    {
      lang: 'zh',
      // ...
    },
  ],
});
```

## i18nSourcePath

- **类型**： `string`
- **默认值**： `path.join(cwd, 'i18n.json')`

指定国际化文案数据源文件的路径。默认情况下，Rspress 从当前工作目录下的 `i18n.json` 读取。例如：

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

export default defineConfig({
  i18nSourcePath: path.join(__dirname, 'config/i18n.json'),
});
```

:::tip

效果与在项目根目录放置 `i18n.json` 文件一致。如果同时配置了 `i18nSource`，`i18nSource` 的数据将会合并并覆盖 `i18nSourcePath` 加载的数据。

:::

## i18nSource

- **类型**： `Record<string, Record<string, string>> | ((value: Record<string, Record<string, string>>) => Record<string, Record<string, string>> | Promise<Record<string, Record<string, string>>>)`
- **默认值**： `{}`

你可以通过这个配置项来修改 Rspress 内置的国际化文案或扩展自定义组件的文案。当扩展文案时，通常配合 [useI18n](https://rspress.rs/zh/ui/hooks/use-i18n.md) 一起使用。

:::tip

与 `i18n.json` 的实现和效果均一致，任选一个使用即可，`i18nSource` 比 `i18n.json` 的优先级高，并且支持函数。

:::

参数 `i18nSource` 是一个对象，其结构为：

```ts
{
  [textKey: string]: {
    [locale: string]: string;
  }
}
```

其中第一层的 `textKey` 是文案的键名，第二层的 `locale` 是语言代码（如 `zh`、`en`），值是对应语言的翻译文本。

下面是一个修改 Rspress 内置国际化文案的示例：

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';
export default defineConfig({
  i18nSource: {
    editLinkText: {
      en: '📝 Edit this page on Gitlab',
      zh: '📝 在 Gitlab 上编辑此页',
    },
  },
});
```

`i18nSource` 也可以是一个函数，例如：

```ts
import { defineConfig } from '@rspress/core';

export default defineConfig({
  i18nSource: async source => {
    for (const key of Object.keys(source)) {
      source[key]['en_US'] = source[key]['en'];
    }
    return source;
  },
});
```

以下是 Rspress 内置的国际化文案：


```ts file="../../../../../packages/core/src/node/runtimeModule/DEFAULT_I18N_TEXT.ts"
import type { I18nText } from '@rspress/core';

// cspell:disable
export const DEFAULT_I18N_TEXT = {
  languagesText: {
    zh: '语言',
    en: 'Languages',
    ja: '言語',
    ko: '언어',
    ru: 'Языки',
  },
  themeText: {
    zh: '主题',
    en: 'Theme',
    ja: 'テーマ',
    ko: '테마',
    ru: 'Тема',
  },
  versionsText: {
    zh: '版本',
    en: 'Versions',
    ja: 'バージョン',
    ko: '버전',
    ru: 'Версии',
  },
  menuTitle: {
    zh: '菜单',
    en: 'Menu',
    ja: 'メニュー',
    ko: '사이드바 메뉴',
    ru: 'Меню',
  },
  outlineTitle: {
    zh: '目录',
    en: 'ON THIS PAGE',
    ja: '目次',
    ko: '이 페이지 목차',
    ru: 'ОГЛАВЛЕНИЕ',
  },
  scrollToTopText: {
    en: 'Back to top',
    zh: '回到顶部',
    ja: 'トップに戻る',
    ko: '맨 위로',
    ru: 'Наверх',
  },
  lastUpdatedText: {
    en: 'Last Updated',
    zh: '最后更新于',
    ja: '最終更新',
    ko: '업데이트 날짜',
    ru: 'Последнее обновление',
  },
  lastUpdatedAuthorText: {
    en: 'by',
    zh: '作者',
    ja: '更新者',
    ko: '작성자',
    ru: 'автор',
  },
  prevPageText: {
    en: 'Previous page',
    zh: '上一页',
    ja: '前のページ',
    ko: '이전 페이지',
    ru: 'Предыдущая страница',
  },
  nextPageText: {
    en: 'Next page',
    zh: '下一页',
    ja: '次のページ',
    ko: '다음 페이지',
    ru: 'Следующая страница',
  },
  sourceCodeText: {
    en: 'Source Code',
    zh: '源码',
    ja: 'ソースコード',
    ko: '소스 코드',
    ru: 'Исходный код',
  },
  searchPlaceholderText: {
    en: 'Search',
    zh: '搜索',
    ja: '検索',
    ko: '검색',
    ru: 'Поиск',
  },
  searchPanelCancelText: {
    en: 'Cancel',
    zh: '取消',
    ja: 'キャンセル',
    ko: '취소',
    ru: 'Отмена',
  },
  searchNoResultsText: {
    en: 'No matching results',
    zh: '未找到与之匹配的结果',
    ja: '一致する結果が見つかりません',
    ko: '일치하는 결과가 없습니다',
    ru: 'Нет результатов, соответствующих запросу',
  },
  searchSuggestedQueryText: {
    en: 'Try searching for different keywords',
    zh: '试试搜索不同关键词',
    ja: '別のキーワードで検索してみてください',
    ko: '다른 키워드로 검색해 보세요',
    ru: 'Попробуйте поискать по другим ключевым словам',
  },
  'overview.filterNameText': {
    en: 'Filter',
    zh: '筛选',
    ja: 'フィルター',
    ko: '필터',
    ru: 'Фильтр',
  },
  'overview.filterPlaceholderText': {
    en: 'Search API',
    zh: '搜索 API',
    ja: 'API を検索',
    ko: 'API 검색',
    ru: 'API поиска',
  },
  'overview.filterNoResultText': {
    en: 'No matching API found',
    zh: '未找到匹配的 API',
    ja: '一致する API が見つかりません',
    ko: '일치하는 API가 없습니다',
    ru: 'Не найден подходящий API',
  },
  openInText: {
    en: 'Open in {{name}}',
    zh: '在 {{name}} 中打开',
    ja: '{{name}} で開く',
    ko: '{{name}}에서 열기',
    ru: 'Открыть в {{name}}',
  },
  copyMarkdownText: {
    en: 'Copy Markdown',
    zh: '复制 Markdown',
    ja: 'Markdown をコピー',
    ko: '마크다운 복사',
    ru: 'Скопировать Markdown',
  },
  copyMarkdownLinkText: {
    en: 'Copy Markdown link',
    zh: '复制 Markdown 链接',
    ja: 'Markdown リンクをコピー',
    ko: '마크다운 링크 복사',
    ru: 'Скопировать ссылку в формате Markdown',
  },
  editLinkText: {
    en: 'Edit this page',
    zh: '编辑此页面',
    ja: 'このページを編集',
    ko: '이 페이지 편집',
    ru: 'Отредактировать страницу',
  },
  codeButtonGroupCopyButtonText: {
    en: 'Copy code',
    zh: '复制代码',
    ja: 'コードをコピー',
    ko: '코드 복사',
    ru: 'Скопировать код',
  },
  codeButtonGroupWrapButtonText: {
    en: 'Toggle code wrap',
    zh: '切换代码换行',
    ja: 'コードの折り返しを切り替え',
    ko: '코드 줄바꿈 전환',
    ru: 'Переключить перенос кода',
  },
  notFoundText: {
    en: 'PAGE NOT FOUND',
    zh: '页面未找到',
    ja: 'ページが見つかりません',
    ko: '페이지를 찾을 수 없음',
    ru: 'СТРАНИЦА НЕ НАЙДЕНА',
  },
  takeMeHomeText: {
    en: 'Take me home',
    zh: '返回首页',
    ja: 'ホームに連れてって',
    ko: '홈으로 이동',
    ru: 'Вернуться на главную',
  },

  promptCopyText: {
    en: 'Copy Prompt',
    zh: '复制 Prompt',
    ja: 'Prompt をコピー',
    ko: '프롬프트 복사',
    ru: 'Скопировать Prompt',
  },
  promptCopiedText: {
    en: 'Copied',
    zh: '已复制',
    ja: 'コピーしました',
    ko: '복사됨',
    ru: 'Скопировано',
  },
  promptExpandText: {
    en: 'Expand',
    zh: '展开',
    ja: '展開',
    ko: '펼치기',
    ru: 'Развернуть',
  },
  promptCollapseText: {
    en: 'Collapse',
    zh: '折叠',
    ja: '折りたたむ',
    ko: '접기',
    ru: 'Свернуть',
  },
} as const satisfies Required<I18nText>;

// cspell:enable

```

## logo \{#logo-1}

- **类型**： `string | { dark: string; light: string }`
- **默认值**： `""`

站点 logo。这个路径将用作导航栏左上角的 logo 路径。例如：

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

export default defineConfig({
  logo: '/logo.png',
});
```

Rspress 会在 `public` 目录中找到你的图标，当然你也可以设置成一个 CDN 地址。

当然你可以针对浅色/暗黑模式设置不同的 logo：

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

export default defineConfig({
  logo: {
    dark: '/logo-dark.png',
    light: '/logo-light.png',
  },
});
```

## logoHref

- **类型**： `string`
- **默认值**： `/${lang}/`

自定义 logo 的链接。默认情况下点击 logo 会跳转到当前语言的首页。例如：

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

export default defineConfig({
  logo: '/logo.png',
  logoHref: 'https://example.com',
});
```

## logoText

- **类型**： `string`
- **默认值**： `""`

站点 logo 文字。这个文字将用作导航栏左上角的 logo 文字。例如：

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

export default defineConfig({
  logoText: 'rspress',
});
```

## outDir

- **类型**： `string`
- **默认值**： `doc_build`

自定义构建站点的输出目录。比如:

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

export default defineConfig({
  outDir: 'doc_build',
});
```

## themeDir

- **类型**： `string`
- **默认值**： `theme`

指定自定义主题目录。默认情况下，Rspress 使用当前工作目录下的 `theme` 目录作为自定义主题目录。你可以通过 `themeDir` 来自定义它。例如：

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

export default defineConfig({
  themeDir: path.join(__dirname, 'my-theme'),
});
```

该配置同时支持相对路径和绝对路径，相对路径相对于当前工作目录。

更多关于自定义主题的内容，请参阅 [自定义主题](https://rspress.rs/zh/guide/basic/custom-theme.md)。

## locales

- **类型**： `Locale[]`

```ts
export interface Locale {
  lang: string;
  label: string;
  title?: string;
  description?: string;
}
```

站点的多语言配置。比如：

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

export default defineConfig({
  locales: [
    {
      lang: 'en-US',
      label: 'English',
      title: 'My Site',
      description: 'My site description',
    },
    {
      lang: 'zh-CN',
      label: '简体中文',
      title: '站点标题',
      description: '站点描述',
    },
  ],
});
```

## head

- **类型**： `string` | `[string, Record<string, string>]` | `(route) => string | [string, Record<string, string>] | undefined`
- 也可以通过 [frontmatter](https://rspress.rs/zh/api/config/config-frontmatter.md#head) 针对每个页面设置

用于设置生产模式下页面 HTML 的 `<head>` 标签中呈现的附加元素。

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

export default defineConfig({
  // ... 其他用户配置
  head: [
    '<meta name="author" content="John Doe">',
    // 或者
    ['meta', { name: 'author', content: 'John Doe' }],
    // [htmlTag, { attrName: attrValue, attrName2: attrValue2 }]
    // 或者
    route => {
      if (route.routePath.startsWith('/jane/'))
        return "<meta name='author' content='Jane Doe'>";
      if (route.routePath.startsWith('/john/'))
        return ['meta', { name: 'author', content: 'John Doe' }];
      // 也可以不返回任何内容
      return undefined;
    },
  ],
});
```

## globalStyles

- **类型**： `string`
- **默认值**： `undefined`

用于添加全局样式，配置为样式文件的路径。例如：

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

export default defineConfig({
  globalStyles: path.join(__dirname, 'styles/global.css'),
});
```

```css title="styles/global.css"
:root {
  --rp-c-brand: #f00;
}
```

## llms

- **类型**：

```ts
boolean | {
  llmsTxt?: (context: LlmsTxtContext) => string | Promise<string>;
  remarkSplitMdxOptions?: RemarkSplitMdxOptions;
}
```

- **默认值**：`false`

是否开启 [SSG-MD](https://rspress.rs/zh/guide/basic/ssg-md.md) 来生成 `llms.txt`、`llms-full.txt` 以及每个页面对应的 Markdown 文件，使你的文档更容易被大语言模型理解。

可通过 `llmsTxt` 基于站点信息和页面分组编排完整的 `llms.txt` 内容。详见[自定义 llms.txt](https://rspress.rs/zh/guide/basic/ssg-md.md#%E8%87%AA%E5%AE%9A%E4%B9%89-llmstxt)。

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

export default defineConfig({
  llms: true,
});
```

:::warning

`llms` 为实验性功能。如果由于代码不兼容 SSR 而无法开启 SSG-MD，请使用 [@rspress/plugin-llms](https://rspress.rs/zh/plugin/official-plugins/llms.md) 作为备选方案。

:::

详细用法、配置选项和实现原理请参阅 [llms.txt（SSG-MD）](https://rspress.rs/zh/guide/basic/ssg-md.md)。

## mediumZoom

- **类型**： `boolean` | `{ selector?: string }`
- **默认值**： `true`

是否开启图片放大功能。默认开启，你可以通过设置 `mediumZoom` 为 `false` 来关闭。

> 底层使用的是 [medium-zoom](https://github.com/francoischalifour/medium-zoom) 库来实现的。

使用示例：

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

export default defineConfig({
  // 关闭图片放大功能
  mediumZoom: false,
  // 配置 CSS 选择器，自定义要放大的图片，默认为 '.rspress-doc img'
  mediumZoom: {
    selector: '.rspress-doc img',
  },
});
```

## search

- **类型**：

```ts
type SearchOptions = {
  searchHooks?: string;
  versioned?: boolean;
  codeBlocks?: boolean;
};
```

:::tip
如果需要从搜索索引中排除某个页面，可以在该页面的 front matter 中设置 [`search: false`](https://rspress.rs/zh/api/config/config-frontmatter.md#search)。
:::

### searchHooks

- **类型**： `string`
- **默认值**： `undefined`

你可以通过 `searchHooks` 参数来增加搜索运行时钩子逻辑，比如：

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

export default defineConfig({
  search: {
    searchHooks: path.join(__dirname, 'searchHooks.ts'),
  },
});
```

关于具体的钩子逻辑，你可以阅读 [自定义搜索功能](https://rspress.rs/zh/guide/advanced/custom-search.md)。

### versioned

- **类型**： `boolean`
- **默认值**： `true`

配置 [`multiVersion`](https://rspress.rs/zh/guide/basic/multi-version.md) 后，默认会为每个版本创建独立的搜索索引，使搜索结果仅包含用户当前所选版本的页面。将 `versioned` 设为 `false` 可以关闭该行为，搜索结果将包含所有版本的文档。

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

export default defineConfig({
  search: {
    versioned: false,
  },
});
```

### codeBlocks

- **类型**： `boolean`
- **默认值**： `true`

是否在搜索的索引中包含代码块的内容，这可以让用户搜索代码块。

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

export default defineConfig({
  search: {
    codeBlocks: false,
  },
});
```

## globalUIComponents

- **类型**： `(string | object)[]`
- **默认值**： `[]`

你可以通过 `globalUIComponents` 参数来增加全局 UI 组件，比如：

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

export default defineConfig({
  globalUIComponents: [path.join(__dirname, 'components', 'MyComponent.tsx')],
});
```

`globalUIComponents` 的每一项可以是一个字符串，代表组件的文件路径；也可以是一个数组，第一项为组件的文件路径，第二项为组件的 props 对象，比如：

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

export default defineConfig({
  globalUIComponents: [
    [
      path.join(__dirname, 'components', 'MyComponent.tsx'),
      {
        foo: 'bar',
      },
    ],
  ],
});
```

当你注册了全局组件之后，Rspress 会自动将这些 React 组件在主题中进行渲染，而不用你手动引入。

通过全局组件，你可以完成诸多自定义的功能，比如:

```tsx title="compUi.tsx"
import React from 'react';

// 需要默认导出一个组件
// 通过 props 来拿到配置中传入的 props 数据
export default function PluginUI(props?: { foo: string }) {
  return <div>This is a global layout component</div>;
}
```

这样，在主题页面中会渲染组件的内容，比如添加**回到顶部按钮**。

同时，你也可以通过全局组件来注册全局副作用。比如：

```tsx title="compSideEffect.tsx"
import { useEffect } from 'react';
import { useLocation } from '@rspress/core/runtime';

// 需要默认导出一个组件
export default function PluginSideEffect() {
  const { pathname } = useLocation();
  useEffect(() => {
    // 组件初次渲染时执行
  }, []);

  useEffect(() => {
    // 路由变化时执行
  }, [pathname]);
  return null;
}
```

这样，在主题页面中会执行组件的副作用。比如以下的一些需要副作用的场景:

- 针对某些页面路由进行重定向操作。
- 对页面的 img 标签进行事件监听，实现图片放大功能。
- 路由变化时，上报不同页面的 PV 数据。
- ......

## multiVersion

- **类型**： `{ default: string; versions: string[] }`

你可以通过 `multiVersion` 参数来增加多版本文档支持，比如：

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

export default defineConfig({
  multiVersion: {
    default: 'v1',
    versions: ['v1', 'v2'],
  },
});
```

其中，`default` 为默认版本，`versions` 为所有版本列表。

## route

- **类型**： `Object`

自定义路由配置。

### route.include

- **类型**： `string[]`
- **默认值**： `[]`

在路由中添加一些额外的文件。默认情况下，只有文档根目录中的文件才会包含在路由中。如果你想在路由中添加一些额外的文件，你可以使用这个选项。例如：

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

export default defineConfig({
  route: {
    include: ['other-dir/**/*.{md,mdx}'],
  },
});
```

> 注意：数组中的字符串支持 glob 模式，填写的 glob 表达式应基于文档的 `root` 目录，并带上对应的 extensions 后缀。

:::note

我们更加推荐在自定义 Rspress 插件中使用 [addPages hook](https://rspress.rs/zh/plugin/system/plugin-api.md#addpages) 来在路由中添加一些额外的文件，这样可以更灵活且更合理地指定页面路由和文件路径/内容。

:::

### route.exclude

- **类型**： `string[]`
- **默认值**： `[]`

从路由中排除一些文件。例如：

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

export default defineConfig({
  route: {
    exclude: ['custom.tsx', 'component/**/*'],
  },
});
```

> 注意：数组中的字符串支持 glob 模式，填写的 glob 表达式应基于文档的 `root` 目录。

### route.excludeConvention

- **类型**： `string[]`
- **默认值**： `['**/_[^_]*']`

为方便用户在 [docs 目录](https://rspress.rs/zh/api/config/config-basic.md#root) 中使用组件，而设置的 [路由约定](https://rspress.rs/zh/guide/use-mdx/components.md)，默认排除以 `_` 开头的文件。

如果你确实需要一些 `_` 开头的路由时，你可以调整这个规则，例如设置为以 `_fragment-` 开头才会被排除：

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

export default defineConfig({
  route: {
    excludeConvention: ['**/_fragment-*'],
  },
});
```

### route.extensions

- **类型**： `string[]`
- **默认值**： `['.js', '.jsx', '.ts', '.tsx', '.md', '.mdx']`

将包含在路由中的文件的扩展名。默认情况下，Rspress 会在路由中包含所有 \`'js'、'jsx'、'ts'、'tsx'、'md'、'mdx' 文件。如果你想自定义扩展名，你可以使用这个选项。例如：

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

export default defineConfig({
  route: {
    extensions: ['.md', '.mdx'],
  },
});
```

### route.cleanUrls

- **类型**： `boolean`
- **默认值**： `false`

开启后可以生成无 `.html` 后缀的链接，URL 可以更加简洁。

:::warning 需要服务器支持

启用此选项可能需要在托管平台上进行额外配置。要使其生效，服务器必须能够在访问 `/foo` 时不经过重定向直接提供 `/foo.html`。

:::

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

export default defineConfig({
  route: {
    cleanUrls: true,
  },
});
```

### route.cleanUrlsRedirect

- **类型**： `boolean`
- **默认值**： `true`

开启后，Rspress 会在客户端启动阶段以实际匹配到的路由为准，规范化浏览器地址栏中的
非规范 URL。目标格式遵循 [`route.cleanUrls`](#routecleanurls)。

`route.cleanUrls` 控制生成链接所使用的首选 URL 格式，
`route.cleanUrlsRedirect` 仅负责规范化浏览器地址栏。

:::warning 客户端路由兜底

该配置会在请求页面的 HTML 和客户端运行时代码加载后执行。它使用
`history.replaceState`，不会返回 HTTP 301/308 响应，因此无法完全替代服务端或
CDN 的 canonical 重定向，尤其不能提供相同的 SEO 效果。托管平台仍需为当前 URL
变体返回正确的 Rspress 页面；如果条件允许，建议优先配置服务端重定向。

:::

#### `cleanUrls: true`

普通页面路由不保留 trailing slash，目录首页路由则会保留。

| 传入 URL               | 匹配路由       | 浏览器 URL 更新                  |
| -------------------- | ---------- | --------------------------- |
| `/file`              | `/file`    | 不更新                         |
| `/file.html`         | `/file`    | `replaceState` 到 `/file`    |
| `/file/`             | `/file`    | `replaceState` 到 `/file`    |
| `/file/index`        | `/file`    | `replaceState` 到 `/file`    |
| `/file/index.html`   | `/file`    | `replaceState` 到 `/file`    |
| `/folder`            | `/folder/` | `replaceState` 到 `/folder/` |
| `/folder.html`       | `/folder/` | `replaceState` 到 `/folder/` |
| `/folder/`           | `/folder/` | 不更新                         |
| `/folder/index`      | `/folder/` | `replaceState` 到 `/folder/` |
| `/folder/index.html` | `/folder/` | `replaceState` 到 `/folder/` |

#### `cleanUrls: false`

普通页面路由使用 `.html`，目录首页路由使用 `/index.html`。

| 传入 URL               | 匹配路由       | 浏览器 URL 更新                            |
| -------------------- | ---------- | ------------------------------------- |
| `/file`              | `/file`    | `replaceState` 到 `/file.html`         |
| `/file.html`         | `/file`    | 不更新                                   |
| `/file/`             | `/file`    | `replaceState` 到 `/file.html`         |
| `/file/index`        | `/file`    | `replaceState` 到 `/file.html`         |
| `/file/index.html`   | `/file`    | `replaceState` 到 `/file.html`         |
| `/folder`            | `/folder/` | `replaceState` 到 `/folder/index.html` |
| `/folder.html`       | `/folder/` | `replaceState` 到 `/folder/index.html` |
| `/folder/`           | `/folder/` | `replaceState` 到 `/folder/index.html` |
| `/folder/index`      | `/folder/` | `replaceState` 到 `/folder/index.html` |
| `/folder/index.html` | `/folder/` | 不更新                                   |

例如，`/zh/guide/start/introduction.html` 和
`/zh/guide/start/introduction/index.html` 都会匹配
`/zh/guide/start/introduction`，最终 URL 会遵循 `cleanUrls` 配置，并保留语言前缀。

Canonical URL 格式与 Cloudflare 的
[HTML handling](https://developers.cloudflare.com/workers/static-assets/routing/advanced/html-handling/)
保持一致，但 Cloudflare 执行的是服务端 HTTP 重定向，本配置只会在浏览器中更新 URL。

将 `cleanUrlsRedirect` 设置为 `false` 可以关闭浏览器 URL 规范化：

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

export default defineConfig({
  route: {
    cleanUrlsRedirect: false,
  },
});
```

### route.localeRedirect


[新增于 v2.0.19](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.19)

- **类型**：`'auto' | 'never' | 'only-default-lang'`
- **默认值**：`'auto'`

控制如何根据 `window.navigator.language` 将首次访问的用户重定向到最匹配的已配置语言：

- `auto`：从任意语言重定向到最匹配的已配置语言。
- `never`：禁用自动语言重定向。
- `only-default-lang`：仅在访问默认语言时重定向。

:::tip 建议使用服务端重定向

该选项在浏览器端执行重定向。生产环境中，如果条件允许，更推荐在服务器或 CDN 边缘完成语言协商与重定向。这样可以在 HTML 下发前完成跳转，并且不依赖客户端 JavaScript。

:::

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

export default defineConfig({
  route: {
    localeRedirect: 'never',
  },
});
```

### route.useTransitions


[新增于 v2.0.17](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.17)

- **类型**： `boolean`
- **默认值**： `true`

启用针对 Rspress 默认 `Link` 组件的并发优化路由。它覆盖 Markdown 和 MDX 内容中的链接，也覆盖侧边栏项等默认主题导航链接。

默认情况下，该选项开启。除非你显式将 `useTransitions` 设置为 `false`，否则内部页面跳转都会被包裹在 React 的 `startTransition` 中。这可以避免新页面内容的重渲染阻塞用户输入，使页面在导航过程中保持响应和可交互。

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

export default defineConfig({
  route: {
    useTransitions: false,
  },
});
```

### route.prefetchLink


[新增于 v2.0.17](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.17)

- **类型**： `boolean`
- **默认值**： `true`

默认情况下，Rspress 的 `Link` 组件会在用户 hover 链接时，预请求对应内部路由的资源；在 touch 设备上也会触发同样的行为。这是一个性能优化手段。将该配置设置为 `false` 可禁用这一行为。

:::tip

在开发环境下，链接预取会和 Rspress 默认开启的 [`dev.lazyCompilation`](https://rsbuild.rs/zh/config/dev/lazy-compilation) 配合使用。按需编译让页面只在被访问时才编译，从而提升启动速度；链接预取则会在 hover 时提前启动目标路由编译，减少首次打开目标路由时的等待。

:::

示例：

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

export default defineConfig({
  route: {
    prefetchLink: false,
  },
});
```

## ssg

- **类型**： `boolean | { experimentalWorker?: boolean; experimentalLoose?: boolean; }`
- **默认值**： `true`

是否开启静态站点生成。Rspress 默认开启该功能，生成 SSG 产物。

如果你的文档站只要求在 CSR 场景下使用，你可以设置 `ssg` 为 `false`，此时 Rspress 会生成 CSR 产物。

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

export default defineConfig({
  ssg: false,
});
```

:::tip

SSG 要求源码支持在 SSR 下编译，如果使用了不兼容 SSR 场景下的代码，会导致编译失败。你可以尝试：

1. 修复不兼容 SSR 场景下的代码，使其兼容 SSR。

2. 设置 `ssg` 为 `false`，但是会失去 SSG 功能。

:::

### experimentalWorker

- **类型**： `boolean`
- **默认值**： `false`

开启后可以使用 Worker 来加速 SSG 过程并降低内存占用，适合大型文档站点，底层基于 [tinypool](https://github.com/tinylibs/tinypool)。

### experimentalExcludeRoutePaths

- **类型**： `(string | RegExp)[]`
- **默认值**： `[]`

开启后一部分页面将不进行 SSG 渲染，直接使用 CSR 下的 html，适合用于大型文档站点绕过一小部分页面的 SSG 错误，不建议主动开启。

## replaceRules

- **类型**： `{ search: string | RegExp; replace: string; }[]`
- **默认值**： `[]`

你可以通过 `replaceRules` 来对整个站点设置文本替换规则，规则会作用于包括 `_meta.json` 文件、frontmatter 配置以及文档内容和标题等所有内容。

```ts title="rspress.config.ts"
export default {
  replaceRules: [
    {
      search: /foo/g,
      replace: 'bar',
    },
  ],
};
```

## languageParity

- **类型**： `Object`

对文档根目录的 md 和 mdx 文件进行扫描，检测是否存在某些语言版本缺失的情况，保证语言一致性。

### languageParity.enable

- **类型**： `boolean`
- **默认值**： `false`

是否启用语言一致性检查。

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

export default defineConfig({
  languageParity: {
    enabled: true,
  },
});
```

### languageParity.include

- **类型**： `string[]`
- **默认值**： `[]`

需要检查的文件夹，默认为文档根目录下所有文件。填写路径时，相对于文档各语言目录。例如：

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

export default defineConfig({
  languageParity: {
    // 包含 zh/en 语言目录下的 posts/foods 和 articles 文件夹
    include: ['posts/foods', 'articles'],
  },
});
```

### languageParity.exclude

- **类型**： `string[]`
- **默认值**： `[]`

从文档目录排除一些文件夹和文件，不进行检查。

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

export default defineConfig({
  languageParity: {
    exclude: ['excluded-directory', 'articles/secret.md'],
  },
});
```
