大家好,這篇文我們來用一下 Rspress。Rspress 是基於 Rsbuild 的靜態網站產生器、並基於 React 進行渲染,其初衷和 Rspack 很像,都是為了解決傳統框架過於冗長的伺服器構建時間,提升開發效率。
Rspress 與一些靜態網站產生器一樣,已經幫我們把樣式都做好了,所以可以用非常快的速度在不寫 HTML, CSS 和 JavaScript 的情況下建置出一個體驗良好、含 RWD 且排版整潔的頁面。其支援 MDX,這表示我們能將另外寫的 React 組件引入使用(例如 Flutter 的 bloc 文件就是運用 Astro + MDX 去解決區塊重用的問題);此外它也支援多國語系和多版本。
開始使用 Rspress
要啟用一個 Rspress 專案,開啟 terminal 並在預計建立專案的目錄下輸入:
# npm
npm create rspress@latest
# yarn
yarn create rspress
# pnpm
pnpm create rspress@latest
啟動開發環境:
# npm
npm run dev
# yarn
yarn dev
# pnpm
pnpm run dev
啟動後到 localhost:3000
應該可以看到畫面:
點擊 Quick Start 就可以進入到內頁:
接下來我們來看一下如何針對頁面進行調整。
建立新頁面
Rspress 採用的路由方式是檔案系統路由(File System Routing),簡單地說就是頁面所在的路徑會等於網頁的路徑。例如內頁的網址路徑為 http://localhost:3000/guide/index.html ,它對應到的會是
docs
├── guide
│ └── index.md
到 docs/guide/index.md
,應該會發現內容與內頁的是相同的,若嘗試進行調整,回到頁面並重整應該也能看見對應異動。
此時建立 docs/guide/info.md
並隨意輸入內容:
# this is my Info page
此時到 http://localhost:3000/guide/info 應該會看到
但眼尖的你應該會發現:為什麼側欄不見了?
如果觀察一下 docs/
資料夾內,應該會分別發現 docs/_meta.json
及 docs/guide/_meta.json
這兩個 json 檔。這兩隻檔案分別用來管理側欄及導航(右上方)的連結,
Rspress 會藉由讀取這些檔案來決定它們應該呈現的樣子,例如我們將 docs/guide/_meta.json
異動為:
["index", "info"]
如果你觀察終端機,應該會發現在你存檔後 Rspress 進行了一次很短暫的 rebuild。回到 http://localhost:3000/guide/info.html 並重整頁面,會發現側欄出現了:
側欄的 _meta.json
中存放的陣列,其可以傳入的為 string
外,也可傳入 Rspress 自定義的 object
。例如我的文件將標題定義為 “this is my Info page”,如果我希望側欄的名稱可以採用 “Info page” 就好,我可以將原本為 "info"
的字串改為:
[
"index",
{
"type": "file",
"name": "info",
"label": "Info page"
}
]
type
代表這筆資料是一隻檔案、 info
代表對應的檔案名稱、 label
則代表在側欄希望顯示的名稱。
若要在側欄中建立子頁面,我們可以先建立資料夾、對應的頁面及 _meta.json
,例如:
docs/
├─ guide/
│ ├─ dev/
│ │ ├─ index.md
│ │ ├─ _meta.json
在 docs/guide/dev/_meta.json
中,先將 index
註冊進去:
["index"]
回到 docs/guide/_meta.json
,我們在此將 dev
這個頁面註冊進去:
[
"index",
{
"type": "file",
"name": "info",
"label": "Info page"
},
{
"type": "dir",
"name": "dev",
"label": "Dev"
}
]
也記得給 docs/guide/dev/index.md
一點內容:
# Index
This is my dev index page.
如果重整畫面,應該可以看到側欄多出一個連結。
正如一開始所說,Rspress 採用檔案系統路由,也就是說子頁面中還能再有子頁面,它可以一直延伸下去,這部分就保留給讀者自行試試看,在子頁面中再加入子頁面,呈現的方式會像是這樣:
而右上方的導航列就單純很多,可以直接看到 docs/_meta.json
的檔案內容:
[
{
"text": "Guide",
"link": "/guide/",
"activeMatch": "/guide/"
},
{
"text": "Hello world",
"link": "/hello/",
"activeMatch": "/hello/"
},
{
"text": "API",
"link": "https://rspress.dev/api/index.html"
}
]
text
代表的是呈現文字、link
代表連結、activeMatch
則代表「連結前綴帶有什麼字串時,會夾帶 active 的狀態」。
更多的側欄和導航設定可參考此。
MDX
MDX 基於 MD 但支援 JSX,也就是說我們可以直接在裡面引入使用 React 組件。我們可以新增一個 docs/components/AppButton.jsx
,並將 docs/guide/info.md
改名為 info.mdx
:
docs/
├─ components/
│ ├─ AppButton.jsx
├─ guide/
│ ├─ info.mdx
AppButton.jsx
可以像是這樣:
export function AppButton({ children}) {
const style = {
color: "white",
backgroundColor: "teal",
padding: "0.5rem 2rem",
borderRadius: "0.5rem",
border: "none",
cursor: "pointer",
}
return (
<button
style={style}
onClick={() => {
alert("Hello, World!");
}}
>
{children}
</button>
);
}
MDX 則可以像是這樣:
import { AppButton } from '../components/AppButton';
# this is my Info page
<AppButton>Click me</AppButton>
實際呈現如下:
點擊時應該也會跳出「Hello, World!」的彈出視窗。
備註:Rspress 並沒有明確指明 React component 適合放在哪個目錄下,其官網所使用的 Rspress 架構中也沒有用到 React component 供參,我個人是覺得組件放置的方式可以以自己看得懂的為佳。
除此之外,也支援 Front Matter、自定義容器等,可以直接參考官方說明。
靜態資源
Rspress 的 favicon、logo 等等都可以透過簡單的設定客製化,可以直接參考根目錄的 rspress.config.ts
:
import * as path from 'node:path';
import { defineConfig } from 'rspress/config';
export default defineConfig({
root: path.join(__dirname, 'docs'),
// 網站標題後方固定會帶的文字,例如「this is my Info page - My Site」
title: 'My Site',
// 網站標題旁的 icon 或稱 favicon
icon: '/rspress-icon.png',
// 這是左上角的 logo
logo: {
light: '/rspress-light-logo.png',
dark: '/rspress-dark-logo.png',
},
// 網站內右上角的 socialLink,預設為 Github 的 Logo 及 Rspress 官網網址
themeConfig: {
socialLinks: [
{
icon: 'github',
mode: 'link',
content: 'https://github.com/web-infra-dev/rspress',
},
],
},
});
文件中的連結都可以使用外部的,例如將 icon 改為:
icon: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2PKprdQdZyMB0EsCU2SnStIPIgiRnoNXExw&s',
重新整理後,網站的 icon 就會變為柴犬:
而主頁的 Logo 和資源則可以藉由更動 docs/index.md
中的內容去異動。
自定義首頁
你可能會希望首頁可以完全自製,我們可以藉由設定 docs/index.md
的內容去辦到:
// docs/components/HomePage.jsx
export function HomePage() {
return (
<div>
<h1>Welcome to the HomePage</h1>
<p>
This is a simple example of a React component that is rendered in the
browser.
</p>
</div>
);
}
// docs/index.md
---
pageType: custom
navbar: false
---
import { HomePage } from './components/HomePage';
<HomePage />
其也支援引入全域樣式和如 Tailwind CSS 的樣式庫。
部署至 Github Page
Rspress 的 Github Page 部署方式是我看過算很清楚也很簡單的,基本上只要照著這份文件的說明貼上設定檔並至對應區塊做好設定,五分鐘內應該就能看到自己的成品被推上 Github Page。
結語
其實我目前使用 Rspress 的總時數也就幾個小時而已,實際要做的成品也還在製作中,過程也就是邊翻官方文件邊試錯,寫這篇文的目的是整理出我自認大家應該會有的調整需求,希望大家可以在半小時內就對它有很快速的認識,並能開始動手實作。
目前我自己嘗試下來,整理出的優點和缺點如下:
優點
- 由於是基於 Rust,建構和打包的速度都非常快
- 模板的內容很少,即使只看起始專案的設定也能大概推論出怎麼進行調整,可塑性也很高
- Rspress 是由中文語系的開發者為主,所以官方文件是有完整中文版的
缺點
- 在異動
_meta.json
時在特定情況下可能會導致 Hot Build 中斷 - Hot Build 時可能會出現 Layout 沒有消失的問題,重新載入頁面才會恢復
整體上來說,我覺得缺點並不會勸退人,因為社群的更新速度很快,這些問題估計也遲早會被修正。
若要深入了解它還能辦到哪些事情,還是得自己看過一次官方文件才能有更完整的認識。最後,希望這篇文有幫助到你,如果內文有任何錯誤也歡迎指出或留言跟我說喔!
References: