Markdown 渲染管線設計:從 MDX 到 HTML 的完整鏈路
技术架构(更新於 2026年5月29日)
Markdown 渲染的挑戰
工具庫的部落格與教學系統需要將 MDX/Markdown 檔案渲染為安全的 HTML。看似簡單,實際涉及:
- 語法擴充:GFM 表格、任務清單、刪除線
- 安全消毒:防止 XSS(使用者不可信內容)
- 程式碼高亮:語法著色的
<pre><code>區塊 - 標題錨點:自動產生 slug 供目錄跳轉
- 內部連結:
/pdf/merge在建置時轉為帶 locale 前綴的連結
unified 生態管線
MDX/Markdown 原文
↓ remark-parse (Markdown → MDAST)
↓ remark-gfm (GFM 擴充)
↓ remark-rehype (MDAST → HAST)
↓ rehype-slug (標題添加 id)
↓ rehype-stringify (HAST → HTML)
HTML 輸出
工具庫在 src/lib/blog/render-mdx.ts 中實作這條管線:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeSlug from 'rehype-slug';
import rehypeStringify from 'rehype-stringify';
const processor = unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype, { allowDangerousHtml: false })
.use(rehypeSlug)
.use(rehypeStringify);
Frontmatter 解析
每篇文章的元資料透過 gray-matter 從 MDX 開頭擷取:
---
title: "文章標題"
description: "SEO 描述"
author: "老張(工具庫站長)"
---
正文內容...
import matter from 'gray-matter';
const { data: frontmatter, content } = matter(rawMdx);
// frontmatter.title → "文章標題"
// content → 正文 Markdown
Frontmatter 用於 SEO metadata、Open Graph 標籤與 JSON-LD 結構化資料。
安全考量
禁止原始 HTML 注入
.use(remarkRehype, { allowDangerousHtml: false })
設為 false 時,Markdown 中的 <script> 標籤會被跳脫為文字,而非執行。
連結安全
外部連結應添加 rel="noopener noreferrer" 與 target="_blank":
// rehype 外掛:為外部連結添加安全屬性
function rehypeExternalLinks() {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'a' && isExternal(node.properties.href)) {
node.properties.target = '_blank';
node.properties.rel = 'noopener noreferrer';
}
});
};
}
多語言內容管理
工具庫的內容檔案組織:
src/content/blog/my-article/
├── meta.json ← 共用元資料(分類、標籤、日期)
├── zh-CN.mdx ← 簡體中文正文
├── zh-TW.mdx ← 繁體中文正文
├── en.mdx ← 英文正文
└── ja.mdx ← 日文正文
meta.json 儲存與語言無關的資料,*.mdx 儲存各語言的正文與 frontmatter。建置時 generateStaticParams 列舉所有 slug × locale 組合以預渲染。
效能優化
建置時渲染 vs 執行時渲染
工具庫選擇建置時渲染(SSG):
next build → 讀取 MDX → unified 處理 → HTML 寫入 out/
執行時 → 直接回傳靜態 HTML(零處理開銷)
相較每次請求都處理 Markdown,SSG 的 TTFB 從 ~200ms 降至 ~50ms。
增量內容更新
新增或修改文章後需要重新 next build。對於 18+ 篇文章 × 4 語言 = 72 個頁面,完整建置約 3–5 分鐘。
與 MDX 元件的關係
目前工具庫使用純 Markdown(非 React 元件 MDX),優點是:
- 渲染管線簡單,無 React SSR 開銷
- 內容檔案可用任何 Markdown 編輯器編輯
- 翻譯工作只需處理純文字
未來若需在文章中嵌入互動元件(如 live demo),可升級至 @next/mdx + React 元件。
總結
Markdown 渲染管線是內容驅動網站的核心基礎設施。remark/rehype 生態提供可組合的處理器鏈,gray-matter 處理元資料,建置時渲染確保極致效能。工具庫的部落格系統正是這套架構的實戰應用。
本站提供瀏覽器本地工具,免註冊即可試用 →
#Markdown#MDX#remark#rehype#内容渲染