Rspress 1-0 正式發佈,基於 Rspack 的高性能靜態站點生成器
今天,我們很高興地跟大家宣佈 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 三者的性能對比情況如下:
如果只說一種最核心的優化手段,那無疑是 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 的源碼,歡迎大家一起參與建設。
快速開始
你可以通過如下的命令很方便地開始一個 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
來配置對應的數據,比如:
配置設計遵循奧卡姆剃刀法則,儘可能避免不必要的配置結構,用最簡單的結構描述意圖。關於 _meta.json 的配置詳情你可以閱讀「自動化導航欄 / 側邊欄」文檔 [1]。
- 編程式配置。通過在 Rspress 配置中指定 nav 和 sidebar 配置項來實現。配置細節可查看 「API 文檔」[2]。
我們推薦在一般情況下使用聲明式配置
,這樣有諸多的好處:
-
配置文件更加簡潔和清晰。
-
文件目錄結構
和側邊欄目錄結構
的對應關係更加直觀。 -
增加或者刪減側邊欄目錄時,直接在當前目錄中操作,而不用前往
rspress.config.ts
配置文件中定位到相應的位置然後添加 / 刪減配置,從而減少了開發上下文切換的成本。
而編程式配置
則在某些需要動態生成配置的場景中非常有用,比如 Rspress 官方的 TypeDoc 插件 [3] 會根據 TypeDoc 提供的一份 json 數據自動轉換爲 nav
和 sidebar
的配置。
MDX 支持
MDX 是一種功能強大的內容開發方式。你不僅僅可以像往常一樣編寫 Markdown 文件,而且可以在 Markdown 的內容中使用 React 組件:
除此之外,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 引擎實現,效果如下:
自定義主題
Rspress 支持兩種自定義主題的方式:
- 基於默認主題擴展。在默認主題的各個組件中,提供了許多插槽讓你能添加自定義的佈局內容,比如接入
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
- 完全自定義主題。如果你想從頭開發一套自定義主題,可以重新自定義 Layout 的內容,並藉助 Rspress 提供的各個 Runtime API (如
usePageData
)來獲取編譯時數據、路由等信息。
關於自定義主題的詳情,你可以參考「自定義主題」文檔 [7]。
插件機制
插件機制是 Rspress 至關重要的部分,它可以讓你在搭建站點的過程中,方便地擴展框架的功能。Rspress 的整體架構如下:
框架整體分爲 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>
);
那麼你可以看到如下的預覽效果:

當然,插件同時也支持移動端預覽模式,你可以通過插件配置開啓:

#### Demo 實時 Playground
對於組件文檔,如果能提供組件的實時編輯的能力,將能大大提高文檔的交互體驗。
爲了實現這個功能,你只需要註冊官方的 playground 插件 [18],然後在 .mdx 文件中聲明你的代碼塊。(這裏以上面的代碼塊爲例)
接着,你將會在文檔中看到下面的 playground 效果:

### 內置流暢的轉場動畫
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_
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/VOei4yfwBkRRDOGRhBXbJA