跳至主要内容

[Docusaurus] v3 升級筆記

使用 Docusaurus 好些時間,一開始遇到 Docusaurus 更新時,都還會小心確認後再行更新。 更新多次沒遇到問題,近來遇到 Docusaurus 提示更新時,往往無腦跟著提示更新。

然後,就炸了。

本文記錄將 Docusaurus 從 v2 升級到 v3 的完整過程與遇到的問題解決方法,並持續補充 v3 各版本升級(目前到 3.10.2)的踩坑紀錄。

升級步驟

1. 套件升級 (Package Upgrade)

直接打 npm install @docusaurus:latest ... 會有些相依套件沒有跟著更新, 造成生成失敗. 需要參考官網 Upgrading to Docusaurus v3 | Docusaurus - Upgrading Dependencies 的說明, 手動修改 package.json 中的設定升級相依套件, 方能正確執行.

npm i @docusaurus/core@latest @docusaurus/preset-classic@latest @docusaurus/theme-mermaid@latest @docusaurus/module-type-aliases@latest @docusaurus/tsconfig@latest @docusaurus/types@latest @docusaurus/faster@latest

2. MDX 語法問題解決

The object shape looks like {username: string, age: number}

Use Android version <5

You can use a generic type like Array<T>

Follow the template "Road to <YOUR_MINOR_VERSION>"

Docusaurus v3 使用 MDX v3 引擎,對於 Markdown 文件中可能會造成 MDX 誤判的 < { 有較嚴格的 lint 標準。升級後一堆文章都因為類似錯誤造成編譯失敗。

常見問題範例

解決方法:官網的 Common MDX Problems 有發生原因和處理方式。

3. 效能提升 (v3.6+)

Docusaurus 3.6 | Docusaurus Docusaurus 3.6 最大的改進就是效能的提升, 須按裝對應套件與新增設定.

npm install @docusaurus/faster

4. 3.9 → 3.10 (2026-08)

3.10.x 是為 v4 鋪路的版本,有兩個會直接讓 build 失敗的變更。

future.experimental_faster 改名為 future.faster

faster 已從 experimental 畢業,舊名在 3.10 會 typecheck 失敗(錯誤訊息會誤導你改成 experimental_router):

future: {
faster: { // 原本是 experimental_faster
swcJsLoader: true,
swcJsMinimizer: true,
swcHtmlMinimizer: true,
lightningCssMinimizer: true,
rspackBundler: true,
mdxCrossCompilerCache: true,
rspackPersistentCache: true,
ssgWorkerThreads: true, // 需搭配下方 v4 flag
},
v4: {
removeLegacyPostBuildHeadAttribute: true,
},
},

ssgWorkerThreads 會硬性檢查 v4.removeLegacyPostBuildHeadAttribute 是否開啟 (configValidation.js 直接 throw)。實測 920 頁:cold build 17.5s → 14.4s, 第二次因 rspack persistent cache 降到 8.0s。

frontmatter 用 tab 縮排會炸掉 build

3.10 把 frontmatter parser 從 gray-matter 換成 @11ty/gray-matter, YAML 縮排用 tab 會直接丟 YAMLException: tab characters must not be used in indentation (3.9 可以過)。這是 Obsidian 存檔的常見樣式,升級前先掃一遍:

# 找出 frontmatter 內含 tab 的檔案(不能用 rg 直接抓,
# 內文的 --- 分隔線會讓 multiline pattern 產生大量誤判)
import pathlib
for p in pathlib.Path('.').rglob('*.md'):
if 'node_modules' in p.parts or 'build' in p.parts: continue
t = p.read_text(encoding='utf-8', errors='ignore')
if not t.startswith('---'): continue
end = t.find('\n---', 3)
if end > 0 and '\t' in t[3:end]: print(p)

其他 v4 準備 flag(future.v4

Flag影響
removeLegacyPostBuildHeadAttribute無 plugin 用 postBuild({head}) 就零風險,且是 ssgWorkerThreads 前置條件
useCssCascadeLayersDocusaurus/Infima CSS 進 @layer,自己的 custom.css 維持 unlayered 而一律勝出。注意 !important 優先序會反轉(layered important > unlayered important)
siteStorageNamespacinglocalStorage key 加站點 namespace,既有訪客的深/淺色偏好會重置一次
fasterByDefault等同 faster: true,已逐項列出就不需要
mdx1CompatDisabledByDefault要先把 :::tip 標題 全部改成 :::tip[標題]。注意這個 preprocessor 對 .md(CommonMark)也會跑,不是只影響 .mdx

另外 siteConfig.onBrokenMarkdownLinks 已棄用(v4 移除),改放 siteConfig.markdown.hooks.onBrokenMarkdownLinks

升級總結

v2 到 v3 升級遇到的問題,幾乎官網文件都有提及。耐心跟著文件修正可順利升級。

主要改進

  • 更快的編譯速度
  • 更嚴格的 MDX 語法檢查
  • 更好的效能優化

參考資源