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

今天,我們很高興地跟大家宣布 Rspress 1.0 正式發(fā)布了!
GitHub 倉庫地址:https://github.com/web-infra-dev/rspress
官網(wǎng)地址:https://rspress.dev
框架定位
Rspress 是由 ByteDance Web Infra 團(tuán)隊(duì)孵化的一款靜態(tài)站點(diǎn)生成器,使用 Rspack 進(jìn)行構(gòu)建,基于 React 框架進(jìn)行渲染,支持 MDX 內(nèi)容開發(fā),主打高性能、簡單易用和定制性強(qiáng)。
Rspress 中內(nèi)置了一套默認(rèn)的文檔主題,你可以通過 Rspress 來快速搭建一個(gè)文檔站點(diǎn),同時(shí)也可以自定義主題,來滿足你的個(gè)性化靜態(tài)站需求,比如博客站、產(chǎn)品主頁等。
當(dāng)然,你也可以接入官方提供的相應(yīng)插件來方便地搭建組件庫文檔。
項(xiàng)目背景
Rspress 最初的形態(tài)是給 Web Infra 團(tuán)隊(duì)內(nèi)部提供文檔工具,在過去在維護(hù)一些稍復(fù)雜的文檔項(xiàng)目的過程中,我們圍繞著以下的幾個(gè)方向來建設(shè) Rspress 本身的能力:
- 構(gòu)建性能。保證足夠快的啟動(dòng)速度,帶來良好的開發(fā)體驗(yàn)。
- MDX 支持。通過 MDX,我們可以方便地復(fù)用文檔片段,以及在文檔中渲染自定義的 React 組件。
- 文檔站基礎(chǔ)能力。包括國際化、多版本支持、全文搜索、組件庫文檔等。
- 可擴(kuò)展性。內(nèi)置插件系統(tǒng),支持通過插件 API 來擴(kuò)展框架功能。
同時(shí)我們意識(shí)到這些也代表了 SSG 站點(diǎn)開發(fā)的一些核心需求。接下來將會(huì)根據(jù)這幾個(gè)方面分別進(jìn)行介紹。
構(gòu)建性能
當(dāng)項(xiàng)目越來越龐大,團(tuán)隊(duì)成員時(shí)常苦惱于冗長的項(xiàng)目啟動(dòng)時(shí)間,開發(fā)體驗(yàn)因此受到了一些負(fù)面影響,并且項(xiàng)目開發(fā)的時(shí)間越長,這種體驗(yàn)的劣化就越為明顯。
我們不禁開始思考,是否能跳出目前社區(qū)工具鏈的限制,突破現(xiàn)有 SSG 框架的性能瓶頸,實(shí)現(xiàn)絕大多數(shù)場(chǎng)景的項(xiàng)目秒啟效果?
接著,我們?cè)谶@個(gè)方向上持續(xù)地探索,最終在 Rspress 上實(shí)現(xiàn)了這樣的效果。以 Rspress 官網(wǎng)文檔的內(nèi)容為例,Rspress、Docusaurus 和 Nextra 三者的性能對(duì)比情況如下:
如果只說一種最核心的優(yōu)化手段,那無疑是 Rust 前端工具鏈。我們主要在兩個(gè)性能敏感部分使用了 Rust 工具鏈:
- 前端 Bundler。傳統(tǒng)的 Bundler 包括 webpack、Rollup 等等,對(duì)于一個(gè)前端工程而言,bundler 是各個(gè)編譯工具鏈的集成樞紐,是一個(gè)非常關(guān)鍵的工程能力,對(duì)項(xiàng)目構(gòu)建性能影響巨大。而 Rspress 使用了團(tuán)隊(duì)內(nèi)部自研的 Rspack,Rspack 是一個(gè)基于 Rust 的 Bundler,內(nèi)置多種性能優(yōu)化手段,比如多線程并行編譯、增量編譯等等,相比社區(qū)傳統(tǒng)的打包工具,有 5~10 倍的性能提升。
- Markdown 編譯器。對(duì)于 SSG 框架中另一大編譯性能瓶頸,即
Markdown 編譯,我們也將這一流程 Rust 化以進(jìn)一步提速,定制出 Rspress 的 Markdown 編譯器(即@rspress/mdx-rs)。這款編譯器相比社區(qū)的 JS 版本的編譯器,有近 20 倍的性能提升:
與此同時(shí),Rspress 內(nèi)部也應(yīng)用了其它的諸多構(gòu)建優(yōu)化手段,比如主題包預(yù)打包、樣式預(yù)生成 等等。這些額外的優(yōu)化手段,配合強(qiáng)有力的 Rust 工具鏈,將 SSG 框架的編譯性能推向了一個(gè)嶄新的高度。
MDX 支持
為了保證內(nèi)容開發(fā)的靈活性,Rspress 選擇支持 MDX 這種內(nèi)容格式。
因?yàn)?MDX 的背后實(shí)際代表了一種組件化的內(nèi)容組織方式,一方面文檔即組件,那么我們可以在不同文檔間復(fù)用文檔片段,另一方面在文檔中可以引入任何自定義 React 組件,大大釋放了文檔開發(fā)的想象力。
文檔站基礎(chǔ)能力
當(dāng)然,Rspress 在文檔站基礎(chǔ)能力的打磨上也做了相當(dāng)多的工作,支持了如下的功能特性:
- 自動(dòng)生成布局,包括導(dǎo)航欄、左側(cè)側(cè)邊欄等等;
- 靜態(tài)站點(diǎn)生成,項(xiàng)目構(gòu)建后直出 HTML;
- 國際化,支持多語言文檔;
- 全文搜索,提供開箱即用的搜索功能;
- 多版本文檔管理;
- 自定義文檔主題;
- 自動(dòng)生成組件 Demo 預(yù)覽及 Playground。
擴(kuò)展機(jī)制
在團(tuán)隊(duì)內(nèi)部我們需要在框架中嵌入一些飛書文檔、點(diǎn)擊關(guān)鍵詞展示詞條卡片、MDX 代碼塊自動(dòng)轉(zhuǎn)換為 Playground 組件等等各種能力,這些能力都需要依托于框架本身足夠完善的擴(kuò)展機(jī)制。而 Rspress 的插件機(jī)制就是為了滿足這一系列的擴(kuò)展能力。
為了讓更多的人可以參與到這樣有趣的事情中,我們開放了 Rspress 的源碼,歡迎大家一起參與建設(shè)。
快速開始
你可以通過如下的命令很方便地開始一個(gè) Rspress 項(xiàng)目:
# npm
npm create rspress@latest
# yarn
yarn create rspress@latest
# pnpm
pnpm create rspress@latest
# bun
bun create rspress@latest
然后執(zhí)行npm run dev 即可啟動(dòng)項(xiàng)目。
具體可以參考官網(wǎng)的「快速開始」文檔:https://rspress.dev/zh/guide/start/getting-started.html。
功能特性
接下來我們來介紹 Rspress 的主要功能特性。
自動(dòng)生成布局
對(duì)于一個(gè)文檔站的搭建而言,除了顯示正文內(nèi)容之外,我們一般還需要以下的幾個(gè)布局模塊:
- 導(dǎo)航欄,用于提供全局性的導(dǎo)航入口;
- 側(cè)邊欄,用于展示當(dāng)前導(dǎo)航下的文章目錄;
- 文章大綱欄,用于展示當(dāng)前頁面的大綱結(jié)構(gòu)。
對(duì)于文檔大綱,Rspress 會(huì)自動(dòng)提取文檔中的各級(jí)標(biāo)題,生成大綱信息,并默認(rèn)展示在文章頁右側(cè),你無需其它操作。
而對(duì)于導(dǎo)航欄和側(cè)邊欄,我們提供了兩種配置方式,你可以選擇其中一種進(jìn)行配置:
- 聲明式 配置。通過在目錄中聲明
_meta.json來配置對(duì)應(yīng)的數(shù)據(jù),比如:
配置設(shè)計(jì)遵循奧卡姆剃刀法則,盡可能避免不必要的配置結(jié)構(gòu),用最簡單的結(jié)構(gòu)描述意圖。關(guān)于 _meta.json 的配置詳情你可以閱讀「自動(dòng)化導(dǎo)航欄/側(cè)邊欄」文檔[1]。
- 編程式配置。通過在 Rspress 配置中指定 nav 和 sidebar 配置項(xiàng)來實(shí)現(xiàn)。配置細(xì)節(jié)可查看 「API 文檔」[2]。
我們推薦在一般情況下使用聲明式配置,這樣有諸多的好處:
- 配置文件更加簡潔和清晰。
-
文件目錄結(jié)構(gòu)和側(cè)邊欄目錄結(jié)構(gòu)的對(duì)應(yīng)關(guān)系更加直觀。 - 增加或者刪減側(cè)邊欄目錄時(shí),直接在當(dāng)前目錄中操作,而不用前往
rspress.config.ts配置文件中定位到相應(yīng)的位置然后添加/刪減配置,從而減少了開發(fā)上下文切換的成本。
而編程式配置則在某些需要?jiǎng)討B(tài)生成配置的場(chǎng)景中非常有用,比如 Rspress 官方的 TypeDoc 插件[3] 會(huì)根據(jù) TypeDoc 提供的一份 json 數(shù)據(jù)自動(dòng)轉(zhuǎn)換為 nav 和 sidebar 的配置。
MDX 支持
MDX 是一種功能強(qiáng)大的內(nèi)容開發(fā)方式。你不僅僅可以像往常一樣編寫 Markdown 文件,而且可以在 Markdown 的內(nèi)容中使用 React 組件:
除此之外,Rspress 還支持了一些特定的語法,如:
- 自定義容器語法。
- FrontMatter 元數(shù)據(jù)定義。
- 代碼行高亮語法。
詳情可以查看「使用 MDX」 文檔[4]。
SSG
Rspress 是一個(gè)標(biāo)準(zhǔn)的 SSG 框架,在生產(chǎn)環(huán)境的構(gòu)建中,它會(huì)自動(dòng)幫你生成靜態(tài)站點(diǎn),即生成各個(gè)頁面的 HTML 內(nèi)容,在構(gòu)建完成之后,HTML 會(huì)出現(xiàn)在默認(rèn)的產(chǎn)物目錄中。
隨后,你可以將這個(gè)產(chǎn)物目錄的內(nèi)容部署到任何靜態(tài)站點(diǎn)托管服務(wù)上,比如 Github Pages、Netlify、Vercel 等等。
同時(shí),我們也提供了配置讓你能夠很方便地自定義 SSG 生成的 HTML 內(nèi)容,詳情可以參考「靜態(tài)站點(diǎn)生成」文檔[5]。
國際化(i18n)
國際化在一個(gè)文檔類型的站點(diǎn)中是一個(gè)很常見的需求,而 Rspress 將國際化的能力封裝得足夠簡單易用,在框架中我們將國際化抽象為如下的需求:
- 如何定義 I18n 數(shù)據(jù)源?
- 如何進(jìn)行不同語言下的站點(diǎn)配置?
- 如何組織不同語言版本的文檔目錄?
- 如何自定義組件中使用 I18n 數(shù)據(jù)源?
框架已經(jīng)為你支持了這些需求場(chǎng)景,你可以根據(jù)官方教程[6]來一步步為你的站點(diǎn)實(shí)現(xiàn)國際化。
多版本文檔
在某些場(chǎng)景中,我們需要進(jìn)行多版本文檔管理,而 Rspress 已經(jīng)內(nèi)置了多版本文檔的支持,一方面你可以通過簡單的配置來開啟這個(gè)能力,另一方面你只需要按照往常的寫法來組織目錄即可,不引入非必要的目錄和概念,將心智負(fù)擔(dān)降到最低:
// 配置文件
import { defineConfig } from 'rspress/config';
export default defineConfig({
multiVersion: {
default: 'v1',
versions: ['v1', 'v2'],
},
});
// 目錄結(jié)構(gòu)
docs
├── v1
│ ├── README.md
│ └── guide
│ └── README.md
└── v2
├── README.md
└── guide
└── README.md
全文搜索
Rspress 中提供開箱即用的全文搜索能力,你無需任何配置即可接入,底層基于開源的 FlexSearch 引擎實(shí)現(xiàn),效果如下:
自定義主題
Rspress 支持兩種自定義主題的方式:
- 基于默認(rèn)主題擴(kuò)展。在默認(rèn)主題的各個(gè)組件中,提供了許多插槽讓你能添加自定義的布局內(nèi)容,比如接入
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'
效果如下:
Rspress 中接入 Documate: https://documate.site/integration/rspress
- 完全自定義主題。如果你想從頭開發(fā)一套自定義主題,可以重新自定義 Layout 的內(nèi)容,并借助 Rspress 提供的各個(gè) Runtime API (如
usePageData)來獲取編譯時(shí)數(shù)據(jù)、路由等信息。
關(guān)于自定義主題的詳情,你可以參考「自定義主題」文檔[7]。
插件機(jī)制
插件機(jī)制是 Rspress 至關(guān)重要的部分,它可以讓你在搭建站點(diǎn)的過程中,方便地?cái)U(kuò)展框架的功能。Rspress 的整體架構(gòu)如下:
框架整體分為 Node 端和瀏覽器運(yùn)行時(shí)兩部分,而通過插件機(jī)制,你可以輕松地?cái)U(kuò)展這兩部分的功能,比如添加 Markdown/MDX 編譯插件、添加自定義路由、添加自定義全局組件、添加 Rspack 插件等等。
值得注意的是,由于底層的 Rspack 對(duì) webpack 提供了良好的兼容,所以你可以在 Rspress 里使用社區(qū)中大部分的 webpack 插件。
插件機(jī)制詳情可以查看介紹文檔[8]。
目前已有的官方插件包括:
- @rspress/plugin-medium-zoom[9]:medium-zoom[10] 集成插件,用于支持 MediumZoom 圖片放大效果。
- @rspress/plugin-last-updated[11]:支持顯示最后更新時(shí)間。
- @rspress/plugin-container-syntax[12]:支持在 Markdown/MDX 中使用
:::container 語法。 - @rspress/plugin-typedoc[13]:TypeDoc[14] 集成插件,用于自動(dòng)生成 TS 模塊的 API 文檔。
- @rspress/plugin-preview[15]:支持代碼塊中的組件預(yù)覽。
- @rspress/plugin-playground[16]:支持代碼塊中的組件預(yù)覽,并提供實(shí)時(shí) Playground。
組件文檔
Demo 預(yù)覽
Rspress 提供了 preview 插件[17],可以自動(dòng)為你生成組件預(yù)覽。當(dāng)你注冊(cè) 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>
);
```
那么你可以看到如下的預(yù)覽效果:
當(dāng)然,插件同時(shí)也支持移動(dòng)端預(yù)覽模式,你可以通過插件配置開啟:
Demo 實(shí)時(shí) Playground
對(duì)于組件文檔,如果能提供組件的實(shí)時(shí)編輯的能力,將能大大提高文檔的交互體驗(yàn)。
為了實(shí)現(xiàn)這個(gè)功能,你只需要注冊(cè)官方的 playground 插件[18],然后在 .mdx 文件中聲明你的代碼塊。(這里以上面的代碼塊為例)
接著,你將會(huì)在文檔中看到下面的 playground 效果:
內(nèi)置流暢的轉(zhuǎn)場(chǎng)動(dòng)畫
View Transition API[19] 是現(xiàn)代瀏覽器原生提供的一組 API,用于實(shí)現(xiàn)頁面跳轉(zhuǎn)過程中的過渡效果。在 Rspress 中我們也跟進(jìn)了這個(gè)特性,基于 View Transition 實(shí)現(xiàn)了文檔的過渡動(dòng)畫,而未使用任何第三方 SPA 的動(dòng)畫方案。在未來,我們也會(huì)探索出更多的動(dòng)畫效果,進(jìn)一步提升體驗(yàn)。
export default defineConfig({
themeConfig: {
// 開啟 View Transition 過渡
enableContentAnimation: true,
},
});
未來規(guī)劃
完善基礎(chǔ)能力
Rspress 目前提供的功能已經(jīng)能夠滿足大多數(shù)的 SSG 項(xiàng)目使用,同時(shí)我們也在未來會(huì)根據(jù)社區(qū)反饋,豐富 Rspress 的基礎(chǔ)能力,滿足更多場(chǎng)景的需求。
補(bǔ)齊 mdx-rs 功能
雖然 mdx-rs 的編譯能力已經(jīng)能勝任大部分場(chǎng)景的純文檔類開發(fā)場(chǎng)景,但目前仍然存在一些不能滿足需求的場(chǎng)景,如 preview 插件和 playground 插件,我們將進(jìn)一步完善這些常用能力。
自定義主題
除了默認(rèn)的文檔主題,我們也會(huì)在未來給 Rspress 添加更豐富的主題,歡迎社區(qū)的小伙伴們來貢獻(xiàn) ????
更加豐富的插件能力
未來我們也會(huì)提供更多的官方插件能力,比如:
- BackTop 插件,在頁面中增加回到頂部效果。
- Google Analytics 插件,給站點(diǎn)集成谷歌分析,收集網(wǎng)站訪問數(shù)據(jù)。
- Sitemap 插件,在構(gòu)建階段生成 sitemap 文件。
- PWA 插件,提供 PWA 集成。
- Client Redirect 插件,提供路由重定向能力。
- ......
持續(xù)優(yōu)化性能和質(zhì)量
性能是 Rspress 的關(guān)鍵優(yōu)勢(shì),隨著項(xiàng)目的不斷迭代,我們會(huì)逐步建立起完善的性能觀測(cè)機(jī)制,防止性能劣化,尋找潛在的性能提升點(diǎn),給社區(qū)用戶持續(xù)提供良好的開發(fā)體驗(yàn)。
同時(shí),我們也會(huì)不斷地完善功能測(cè)試用例,提升測(cè)試覆蓋率,保障項(xiàng)目長期的健康發(fā)展。
致謝
Rspress 的設(shè)計(jì)受到了社區(qū)中諸多項(xiàng)目的啟發(fā)和支持,在這里對(duì)這些前輩表示致敬和感謝:
- VitePress[20] 項(xiàng)目(由 @尤雨溪 創(chuàng)建),其中 SSG 的實(shí)現(xiàn)架構(gòu)為 Rspress 提供了參考。
- Vuepress[21] 項(xiàng)目(由 @尤雨溪 和 @ulivz 創(chuàng)建),其中的插件機(jī)制設(shè)計(jì)啟發(fā)了 Rspress 的插件 API 設(shè)計(jì)。
- Nextra[22] 項(xiàng)目(由 @shuding 創(chuàng)建),Rspress 的
_meta.json設(shè)計(jì)靈感來自于此,并在 Nextra 的基礎(chǔ)上進(jìn)行了簡化。 - mdxjs-rs[23] 項(xiàng)目(由 @wooorm 創(chuàng)建),給 @rspress/mdx-rs 節(jié)省了諸多的開發(fā)成本。
- NAPI-RS[24] 項(xiàng)目(由 @Brooooooklyn 創(chuàng)建),為 mdx-rs 的 node-binding 實(shí)現(xiàn)提供了支持。
- Dumi[25](由 @PeachScript 創(chuàng)建),給 Rspress 的移動(dòng)端組件 Demo 預(yù)覽功能提供了設(shè)計(jì)上的參考。
參考資料
[1]「自動(dòng)化導(dǎo)航欄/側(cè)邊欄」文檔: 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]「靜態(tài)站點(diǎn)生成」文檔: 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
