Rspress 1.0 正式开源,比 Docusaurus 快十倍!

前端三元同学

共 10846字,需浏览 22分钟

 ·

2023-10-16 02:48

fad01952a35cdc49507516c8fa8933df.webp

今天,我们很高兴地跟大家宣布 Rspress 1.0 正式发布了!

GitHub 仓库地址:https://github.com/web-infra-dev/rspress

官网地址:https://rspress.dev

框架定位

Rspress 是由 ByteDance Web Infra 团队孵化的一款静态站点生成器,使用 Rspack 进行构建,基于 React 框架进行渲染,支持 MDX 内容开发,主打高性能、简单易用和定制性强。

Rspress 中内置了一套默认的文档主题,你可以通过 Rspress 来快速搭建一个文档站点,同时也可以自定义主题,来满足你的个性化静态站需求,比如博客站、产品主页等。

当然,你也可以接入官方提供的相应插件来方便地搭建组件库文档。

项目背景

Rspress 最初的形态是给 Web Infra 团队内部提供文档工具,在过去在维护一些稍复杂的文档项目的过程中,我们围绕着以下的几个方向来建设 Rspress 本身的能力:

  • 构建性能。保证足够快的启动速度,带来良好的开发体验。
  • MDX 支持。通过 MDX,我们可以方便地复用文档片段,以及在文档中渲染自定义的 React 组件。
  • 文档站基础能力。包括国际化、多版本支持、全文搜索、组件库文档等。
  • 可扩展性。内置插件系统,支持通过插件 API 来扩展框架功能。

同时我们意识到这些也代表了 SSG 站点开发的一些核心需求。接下来将会根据这几个方面分别进行介绍。

构建性能

当项目越来越庞大,团队成员时常苦恼于冗长的项目启动时间,开发体验因此受到了一些负面影响,并且项目开发的时间越长,这种体验的劣化就越为明显。

我们不禁开始思考,是否能跳出目前社区工具链的限制,突破现有 SSG 框架的性能瓶颈,实现绝大多数场景的项目秒启效果?

接着,我们在这个方向上持续地探索,最终在 Rspress 上实现了这样的效果。以 Rspress 官网文档的内容为例,Rspress、Docusaurus 和 Nextra 三者的性能对比情况如下:

2684790f0a994299d100edf5acf0ba7d.webp 226477f0884b8447df43ba1ac8c58fe7.webp 9dc43d78778ccf7f031803c415e57455.webp

如果只说一种最核心的优化手段,那无疑是 Rust 前端工具链。我们主要在两个性能敏感部分使用了 Rust 工具链:

  • 前端 Bundler。传统的 Bundler 包括 webpack、Rollup 等等,对于一个前端工程而言,bundler 是各个编译工具链的集成枢纽,是一个非常关键的工程能力,对项目构建性能影响巨大。而 Rspress 使用了团队内部自研的 Rspack,Rspack 是一个基于 Rust 的 Bundler,内置多种性能优化手段,比如多线程并行编译、增量编译等等,相比社区传统的打包工具,有 5~10 倍的性能提升。
  • Markdown 编译器。对于 SSG 框架中另一大编译性能瓶颈,即Markdown 编译,我们也将这一流程 Rust 化以进一步提速,定制出 Rspress 的 Markdown 编译器(即@rspress/mdx-rs)。这款编译器相比社区的 JS 版本的编译器,有近 20 倍的性能提升:
586e9127a905d441c5d32dc0b92972e2.webp

与此同时,Rspress 内部也应用了其它的诸多构建优化手段,比如主题包预打包样式预生成 等等。这些额外的优化手段,配合强有力的 Rust 工具链,将 SSG 框架的编译性能推向了一个崭新的高度。

MDX 支持

为了保证内容开发的灵活性,Rspress 选择支持 MDX 这种内容格式。

因为 MDX 的背后实际代表了一种组件化的内容组织方式,一方面文档即组件,那么我们可以在不同文档间复用文档片段,另一方面在文档中可以引入任何自定义 React 组件,大大释放了文档开发的想象力。

文档站基础能力

当然,Rspress 在文档站基础能力的打磨上也做了相当多的工作,支持了如下的功能特性:

  • 自动生成布局,包括导航栏、左侧侧边栏等等;
  • 静态站点生成,项目构建后直出 HTML;
  • 国际化,支持多语言文档;
  • 全文搜索,提供开箱即用的搜索功能;
  • 多版本文档管理;
  • 自定义文档主题;
  • 自动生成组件 Demo 预览及 Playground。

扩展机制

在团队内部我们需要在框架中嵌入一些飞书文档、点击关键词展示词条卡片、MDX 代码块自动转换为 Playground 组件等等各种能力,这些能力都需要依托于框架本身足够完善的扩展机制。而 Rspress 的插件机制就是为了满足这一系列的扩展能力。

为了让更多的人可以参与到这样有趣的事情中,我们开放了 Rspress 的源码,欢迎大家一起参与建设。

快速开始

你可以通过如下的命令很方便地开始一个 Rspress 项目:

      # npm
npm create rspress@latest
# yarn
yarn create rspress@latest
# pnpm
pnpm create rspress@latest
# bun
bun create rspress@latest

然后执行npm run dev 即可启动项目。

具体可以参考官网的「快速开始」文档:https://rspress.dev/zh/guide/start/getting-started.html。

功能特性

接下来我们来介绍 Rspress 的主要功能特性。

自动生成布局

对于一个文档站的搭建而言,除了显示正文内容之外,我们一般还需要以下的几个布局模块:

  • 导航栏,用于提供全局性的导航入口;
  • 侧边栏,用于展示当前导航下的文章目录;
  • 文章大纲栏,用于展示当前页面的大纲结构。

对于文档大纲,Rspress 会自动提取文档中的各级标题,生成大纲信息,并默认展示在文章页右侧,你无需其它操作。

而对于导航栏和侧边栏,我们提供了两种配置方式,你可以选择其中一种进行配置:

  • 声明式 配置。通过在目录中声明 _meta.json 来配置对应的数据,比如:
358bb1bff9b2e42c1fcd4ea86b9d451a.webp

配置设计遵循奥卡姆剃刀法则,尽可能避免不必要的配置结构,用最简单的结构描述意图。关于 _meta.json 的配置详情你可以阅读「自动化导航栏/侧边栏」文档[1]。

  • 编程式配置。通过在 Rspress 配置中指定 nav 和 sidebar 配置项来实现。配置细节可查看 「API 文档」[2]。

我们推荐在一般情况下使用声明式配置,这样有诸多的好处:

  1. 配置文件更加简洁和清晰。
  2. 文件目录结构侧边栏目录结构的对应关系更加直观。
  3. 增加或者删减侧边栏目录时,直接在当前目录中操作,而不用前往 rspress.config.ts 配置文件中定位到相应的位置然后添加/删减配置,从而减少了开发上下文切换的成本。

编程式配置则在某些需要动态生成配置的场景中非常有用,比如 Rspress 官方的 TypeDoc 插件[3] 会根据 TypeDoc 提供的一份 json 数据自动转换为 navsidebar 的配置。

MDX 支持

MDX 是一种功能强大的内容开发方式。你不仅仅可以像往常一样编写 Markdown 文件,而且可以在 Markdown 的内容中使用 React 组件:

b961dabfc56b6e502c3a2e3fc3d20e03.webp

除此之外,Rspress 还支持了一些特定的语法,如:

  • 自定义容器语法。
  • FrontMatter 元数据定义。
  • 代码行高亮语法。

详情可以查看「使用 MDX」 文档[4]。

SSG

Rspress 是一个标准的 SSG 框架,在生产环境的构建中,它会自动帮你生成静态站点,即生成各个页面的 HTML 内容,在构建完成之后,HTML 会出现在默认的产物目录中。

随后,你可以将这个产物目录的内容部署到任何静态站点托管服务上,比如 Github Pages、Netlify、Vercel 等等。

同时,我们也提供了配置让你能够很方便地自定义 SSG 生成的 HTML 内容,详情可以参考「静态站点生成」文档[5]。

国际化(i18n)

国际化在一个文档类型的站点中是一个很常见的需求,而 Rspress 将国际化的能力封装得足够简单易用,在框架中我们将国际化抽象为如下的需求:

  • 如何定义 I18n 数据源?
  • 如何进行不同语言下的站点配置?
  • 如何组织不同语言版本的文档目录?
  • 如何自定义组件中使用 I18n 数据源?

框架已经为你支持了这些需求场景,你可以根据官方教程[6]来一步步为你的站点实现国际化。

多版本文档

在某些场景中,我们需要进行多版本文档管理,而 Rspress 已经内置了多版本文档的支持,一方面你可以通过简单的配置来开启这个能力,另一方面你只需要按照往常的写法来组织目录即可,不引入非必要的目录和概念,将心智负担降到最低:

      // 配置文件
import { defineConfig } from 'rspress/config';

export default defineConfig({
  multiVersion: {
    default'v1',
    versions: ['v1''v2'],
  },
});
      // 目录结构
docs
├── v1
│   ├── README.md
│   └── guide
│       └── README.md
└── v2
    ├── README.md
    └── guide
        └── README.md

全文搜索

Rspress 中提供开箱即用的全文搜索能力,你无需任何配置即可接入,底层基于开源的 FlexSearch 引擎实现,效果如下:

7139170a19b0def435b5d871671b6d09.webp

自定义主题

Rspress 支持两种自定义主题的方式:

  1. 基于默认主题扩展。在默认主题的各个组件中,提供了许多插槽让你能添加自定义的布局内容,比如接入 documate 提供的 AI 问答组件:
      // theme/index.tsx
import Theme from 'rspress/theme'
import { NoSSR } from 'rspress/runtime'
import { Documate } from '@documate/react'
import '@documate/react/dist/style.css'

const Layout = () => (
  <Theme.Layout
    afterNavTitle={
      <NoSSR>
        <Documate endpoint="" />
      </NoSSR>
    }
  /
>
)

export default {
  ...Theme,
  Layout,
}

export * from 'rspress/theme'

效果如下:

183cee6a56768eacb1aa638137edb68d.webp

Rspress 中接入 Documate: https://documate.site/integration/rspress

  1. 完全自定义主题。如果你想从头开发一套自定义主题,可以重新自定义 Layout 的内容,并借助 Rspress 提供的各个 Runtime API (如 usePageData)来获取编译时数据、路由等信息。

关于自定义主题的详情,你可以参考「自定义主题」文档[7]。

插件机制

插件机制是 Rspress 至关重要的部分,它可以让你在搭建站点的过程中,方便地扩展框架的功能。Rspress 的整体架构如下:

04ce1be4909939a6cc399dfc24bdf2e0.webp

框架整体分为 Node 端和浏览器运行时两部分,而通过插件机制,你可以轻松地扩展这两部分的功能,比如添加 Markdown/MDX 编译插件、添加自定义路由、添加自定义全局组件、添加 Rspack 插件等等。

值得注意的是,由于底层的 Rspack 对 webpack 提供了良好的兼容,所以你可以在 Rspress 里使用社区中大部分的 webpack 插件。

插件机制详情可以查看介绍文档[8]。

目前已有的官方插件包括:

  • @rspress/plugin-medium-zoom[9]:medium-zoom[10] 集成插件,用于支持 MediumZoom 图片放大效果。
  • @rspress/plugin-last-updated[11]:支持显示最后更新时间。
  • @rspress/plugin-container-syntax[12]:支持在 Markdown/MDX 中使用 ::: container 语法。
  • @rspress/plugin-typedoc[13]:TypeDoc[14] 集成插件,用于自动生成 TS 模块的 API 文档。
  • @rspress/plugin-preview[15]:支持代码块中的组件预览。
  • @rspress/plugin-playground[16]:支持代码块中的组件预览,并提供实时 Playground。

组件文档

Demo 预览

Rspress 提供了 preview 插件[17],可以自动为你生成组件预览。当你注册 preview 插件后,在 mdx 文件中声明如下的代码块:

      
        ```jsx
import React from "react";
import { Tag, Space } from "@arco-design/web-react";
import "@arco-design/web-react/dist/css/arco.css";
const COLORS = ["red", "orangered", "orange", "gold", "lime", "green", "cyan", "blue", "arcoblue", "purple", "pinkpurple", "magenta", "gray"];

export default () => (
  <Space wrap>
    {COLORS.map((color, i) => (
      <Tag key={i} color={color}>
        {color}
      </Tag>
    ))}
  </Space>
);
```

那么你可以看到如下的预览效果:

381b37540e58de039696c46b1a329add.webp

当然,插件同时也支持移动端预览模式,你可以通过插件配置开启:

11f6d81fcbefee369bfbb6449214215a.webp

Demo 实时 Playground

对于组件文档,如果能提供组件的实时编辑的能力,将能大大提高文档的交互体验。

为了实现这个功能,你只需要注册官方的 playground 插件[18],然后在 .mdx 文件中声明你的代码块。(这里以上面的代码块为例)

接着,你将会在文档中看到下面的 playground 效果:

1af3b9ebf4247b3695e7f4bd4561137b.webp

内置流畅的转场动画

View Transition API[19] 是现代浏览器原生提供的一组 API,用于实现页面跳转过程中的过渡效果。在 Rspress 中我们也跟进了这个特性,基于 View Transition 实现了文档的过渡动画,而未使用任何第三方 SPA 的动画方案。在未来,我们也会探索出更多的动画效果,进一步提升体验。

      export default defineConfig({
  themeConfig: {
    // 开启 View Transition 过渡
    enableContentAnimation: true,
  },
});

未来规划

完善基础能力

Rspress 目前提供的功能已经能够满足大多数的 SSG 项目使用,同时我们也在未来会根据社区反馈,丰富 Rspress 的基础能力,满足更多场景的需求。

补齐 mdx-rs 功能

虽然 mdx-rs 的编译能力已经能胜任大部分场景的纯文档类开发场景,但目前仍然存在一些不能满足需求的场景,如 preview 插件和 playground 插件,我们将进一步完善这些常用能力。

自定义主题

除了默认的文档主题,我们也会在未来给 Rspress 添加更丰富的主题,欢迎社区的小伙伴们来贡献 👏🏻

更加丰富的插件能力

未来我们也会提供更多的官方插件能力,比如:

  • BackTop 插件,在页面中增加回到顶部效果。
  • Google Analytics 插件,给站点集成谷歌分析,收集网站访问数据。
  • Sitemap 插件,在构建阶段生成 sitemap 文件。
  • PWA 插件,提供 PWA 集成。
  • Client Redirect 插件,提供路由重定向能力。
  • ......

持续优化性能和质量

性能是 Rspress 的关键优势,随着项目的不断迭代,我们会逐步建立起完善的性能观测机制,防止性能劣化,寻找潜在的性能提升点,给社区用户持续提供良好的开发体验。

同时,我们也会不断地完善功能测试用例,提升测试覆盖率,保障项目长期的健康发展。

致谢

Rspress 的设计受到了社区中诸多项目的启发和支持,在这里对这些前辈表示致敬和感谢:

  • VitePress[20] 项目(由 @尤雨溪 创建),其中 SSG 的实现架构为 Rspress 提供了参考。
  • Vuepress[21] 项目(由 @尤雨溪 和 @ulivz 创建),其中的插件机制设计启发了 Rspress 的插件 API 设计。
  • Nextra[22] 项目(由 @shuding 创建),Rspress 的 _meta.json 设计灵感来自于此,并在 Nextra 的基础上进行了简化。
  • mdxjs-rs[23] 项目(由 @wooorm 创建),给 @rspress/mdx-rs 节省了诸多的开发成本。
  • NAPI-RS[24] 项目(由 @Brooooooklyn 创建),为 mdx-rs 的 node-binding 实现提供了支持。
  • Dumi[25](由 @PeachScript 创建),给 Rspress 的移动端组件 Demo 预览功能提供了设计上的参考。

参考资料

[1]

「自动化导航栏/侧边栏」文档: https://rspress.dev/zh/guide/basic/auto-nav-sidebar.html

[2]

「API 文档」: https://rspress.dev/zh/api/config/config-theme.html#nav

[3]

TypeDoc 插件: https://rspress.dev/plugin/official-plugins/typedoc.html

[4]

「使用 MDX」 文档: https://rspress.dev/zh/guide/basic/use-mdx.html

[5]

「静态站点生成」文档: https://rspress.dev/zh/guide/basic/ssg.html

[6]

官方教程: https://rspress.dev/zh/guide/default-theme/i18n.html

[7]

「自定义主题」文档: https://rspress.dev/zh/guide/advanced/custom-theme.html

[8]

介绍文档: https://rspress.dev/zh/plugin/system/introduction.html

[9]

@rspress/plugin-medium-zoom: https://rspress.dev/zh/plugin/official-plugins/medium-zoom.html

[10]

medium-zoom: https://github.com/francoischalifour/medium-zoom

[11]

@rspress/plugin-last-updated: https://rspress.dev/zh/plugin/official-plugins/last-updated.html

[12]

@rspress/plugin-container-syntax: https://rspress.dev/zh/plugin/official-plugins/container-syntax.html

[13]

@rspress/plugin-typedoc: https://rspress.dev/zh/plugin/official-plugins/typedoc.html

[14]

TypeDoc: https://github.com/TypeStrong/typedoc

[15]

@rspress/plugin-preview: https://rspress.dev/zh/plugin/official-plugins/preview.html

[16]

@rspress/plugin-playground: https://rspress.dev/zh/plugin/official-plugins/playground.html

[17]

preview 插件: https://rspress.dev/zh/plugin/official-plugins/preview

[18]

playground 插件: https://rspress.dev/zh/plugin/official-plugins/playground.html

[19]

View Transition API: https://developer.mozilla.org/zh-CN/docs/Web/API/View_Transitions_API

[20]

VitePress: https://vitepress.vuejs.org/

[21]

Vuepress: https://vuepress.vuejs.org/

[22]

Nextra: https://nextra.site/

[23]

mdxjs-rs: https://github.com/wooorm/mdxjs-rs

[24]

NAPI-RS: https://github.com/napi-rs/napi-rs

[25]

Dumi: https://github.com/umijs/dumi

浏览 41
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报