Rspress 1.0 正式发布,基于 Rspack 的高性能静态站点生成器!

GitHub 仓库地址:github.com/web-infra-d...

官网地址:rspress.dev

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

框架定位

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

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

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

项目背景

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

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

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

构建性能

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

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

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

如果只说一种最核心的优化手段,那无疑是 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 倍的性能提升:

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

MDX 支持

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

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

文档站基础能力

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

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

扩展机制

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

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

GitHub 仓库地址: github.com/web-infra-d...

快速开始

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

perl 复制代码
# npm
npm create rspress@latest
# yarn
yarn create rspress@latest
# pnpm
pnpm create rspress@latest
# bun
bun create rspress@latest

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

具体可以参考官网的「快速开始」文档: rspress.dev/zh/guide/st...

功能特性

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

自动生成布局

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

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

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

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

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

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

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

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

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

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

MDX 支持

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

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

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

详情可以查看「使用 MDX」 文档

SSG

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

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

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

国际化(i18n)

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

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

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

多版本文档

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

ts 复制代码
// 配置文件
import { defineConfig } from 'rspress/config';

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

全文搜索

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

自定义主题

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

  1. 基于默认主题扩展。在默认主题的各个组件中,提供了许多插槽让你能添加自定义的布局内容,比如接入 documate 提供的 AI 问答组件:
ts 复制代码
// 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'

效果如下:

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

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

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

插件机制

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

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

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

插件机制详情可以查看介绍文档

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

组件文档

Demo 预览

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

md 复制代码
```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>
);
```

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

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

Demo 实时 Playground

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

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

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

内置流畅的转场动画

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

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

与其它 SSG 框架的区别

与 Docusaurus 的区别

[Docusaurus](docusaurus.io/ 'Docusaurus' "Docusaurus") 是 Meta 开源的一款 SSG 框架,它和 Rspress 一样使用 React 作为渲染框架,且支持 MDX,但 Rspress 与 Docusaurus 的区别主要在于:

  1. Rspress 的构建性能更好。Rspress 基于 Rust 前端工具链,项目启动/构建速度快于 Docusaurus 5 ~ 10 倍。
  2. Rspress 的配置更简单,上手成本更低。Rspress 的配置更加简单,不引入过多的概念,尽可能降低心智负担,比如提供开箱即用的搜索功能、符合直觉的多版本文档管理方式等等。
  3. Rspress 架构上对 Bundler 提供了更上层的抽象。对于 webpack、Rspack 这类底层的 Bundler,其配置项繁琐且不易上手。Dockusaurus 选择直接暴露底层 Bundler 的配置项,而 Rspress 则对 Bundler 进行了更上层的抽象(未来我们也会把这层方案单独进行开源),提供了更加简单易用的配置项,比如你可以通过 builderConfig.html.tags 配置轻松添加 <head> 中的标签,而不用通过 Bundler 来注册 html-webpack-plugin 相关插件。

与 Nextra 的区别

[Nextra](nextra.vercel.app/ 'Nextra' "Nextra") 是 Vercel 开源的一款 SSG 框架,它也和 Rspress 一样使用 React 作为渲染框架,且支持 MDX。Rspress 与 Nextra 的区别主要在于:

  1. Rspress 的构建性能更好。这一点可参考「与 Docusaurus 的区别」。
  2. Rspress 整体更加轻量。Nextra 需要依赖 Next.js,其 SSG 流程也是基于 Next.js 的,因此 SSG 产物中并非纯粹的 HTML 文件,而是额外包含了一些 Next.js 的运行时代码,一方面导致了 Nextra 的产物体积更大,另一方面需要在部署时以应用的方式部署(使用 next start 命令),而不能以纯静态站点的方式部署。但 Rspress 没有和任何应用框架绑定,因此产物更加轻量,可以很方便地以纯静态站点的方式部署。

与 VitePress 的区别

[VitePress](vitepress.dev/ 'VitePress' "VitePress") 是一款基于 Vite 静态站点生成器,它的特点是使用 Vue 作为渲染框架,且性能非常优秀。Rspress 与 VitePress 的区别主要在于:

  1. Rspress 使用 React 作为渲染框架,而 VitePress 使用 Vue 作为渲染框架。
  2. Rspress 使用 MDX 作为内容开发方式,而 VitePress 使用 Markdown 作为内容开发方式,并在 Markdown 中支持 Vue 组件,这同时也导致了底层编译工具链实现上的差异。
  3. 构建性能上,在开发阶段,Rspress 和 VitePress 都能很快地启动一个项目,而在生产环境下,VitePress 需要基于 Rollup 打包项目,因此会面临其他基于 JavaScript 的工具链类似的性能问题,此时 Rspress 会有更快的构建速度。

未来规划

完善基础能力

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

补齐 mdx-rs 功能

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

自定义主题

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

更加丰富的插件能力

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

  • BackTop 插件,在页面中增加回到顶部效果。

  • Google Analytics 插件,给站点集成谷歌分析,收集网站访问数据。

  • Sitemap 插件,在构建阶段生成 sitemap 文件。

  • PWA 插件,提供 PWA 集成。

  • Client Redirect 插件,提供路由重定向能力。

  • ......

持续优化性能和质量

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

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

致谢

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

  • VitePress 项目(由 @尤雨溪 创建),其中 SSG 的实现架构为 Rspress 提供了参考。
  • Vuepress 项目(由 @尤雨溪 和 @ulivz 创建),其中的插件机制设计启发了 Rspress 的插件 API 设计。
  • Nextra 项目(由 @shuding 创建),Rspress 的 _meta.json 设计灵感来自于此,并在 Nextra 的基础上进行了简化。
  • mdxjs-rs 项目(由 @wooorm 创建),给 @rspress/mdx-rs 节省了诸多的开发成本。
  • NAPI-RS 项目(由 @Brooooooklyn 创建),为 mdx-rs 的 node-binding 实现提供了支持。
  • Dumi(由 @PeachScript 创建),给 Rspress 的移动端组件 Demo 预览功能提供了设计上的参考。
相关推荐
编程零零七2 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
北岛寒沫3 小时前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
everyStudy3 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
(⊙o⊙)~哦4 小时前
JavaScript substring() 方法
前端
无心使然云中漫步4 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者4 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_5 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
麒麟而非淇淋6 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120536 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab
阿树梢6 小时前
【Vue】VueRouter路由
前端·javascript·vue.js