喂!我是 Wei

Front-End Engineer

Be a Problem Solver.

⌘K

導覽

所有文章緣起互動小功能

文章分類

目錄
為什麼選擇 Shiki?安裝套件設定步驟第一步:修改 lib/posts.ts第二步:建立自訂 <pre> 元件(可選,加複製按鈕用)第三步:在 app/globals.css 加入 code block 基礎樣式在文章中寫 Code Block進階功能標示指定行數顯示檔名主題設定小結

相關文章

Next.js Blog 實作文章目錄(TOC)

2026年3月7日

在 Next.js 使用 MDX 撰寫技術文章

2026年3月6日

前端工程師面試題:CSR、SSR、SSG 差在哪?Next.js 為什麼適合 SEO?

2026年6月2日

最新文章
全部 →
前端 CI/CD 與正式環境除錯:從 Pull Request 到事故排查
2026-06-24
即時資料怎麼選?Polling、SSE、WebSocket 比較
2026-06-23
前端系統設計:如何拆元件、資料流與大型專案架構?
2026-06-22
無障礙不是加 ARIA:語意化 HTML、鍵盤操作與焦點管理
2026-06-21
CSS 與 RWD 面試整理:Flexbox、Grid、定位與層疊脈絡
2026-06-19
← 返回文章列表

Next.js Blog 加入程式碼高亮(Shiki + rehype-pretty-code)

2026年3月6日·約 5 分鐘閱讀·
Next.jsMDXShikirehype-pretty-code

在技術 Blog 中,程式碼區塊幾乎是最重要的內容之一。

如果只是使用普通 Markdown 顯示程式碼,通常只會是單純的文字區塊,閱讀體驗並不理想。常見的技術文章網站都會有語法高亮(Syntax Highlighting),讓程式碼更容易閱讀。

在 Next.js + MDX 的 Blog 中,一個很常見的做法是使用 Shiki 搭配 rehype-pretty-code。


為什麼選擇 Shiki?

Shiki 是 VS Code 底層使用的語法高亮引擎,也就是說,Shiki 的高亮效果基本上就是 VS Code 的顯示效果。

  • 支援大量程式語言
  • 顏色主題豐富(內建 VS Code 所有主題)
  • 高亮效果非常準確
  • 與 MDX 生態系整合良好

安裝套件

npm install rehype-pretty-code shiki

設定步驟

第一步:修改 lib/posts.ts

在 compileMDX 的 rehypePlugins 陣列中加入 rehype-pretty-code:

lib/posts.ts
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
 
// 在 getPostBySlug 裡的 compileMDX 選項加入:
const { content } = await compileMDX({
  source: mdxContent,
  options: {
    mdxOptions: {
      rehypePlugins: [
        rehypeSlug,
        rehypeAutolinkHeadings,
        [
          rehypePrettyCode,
          {
            theme: {
              dark: "github-dark",
              light: "github-light",
            },
            keepBackground: false,
          },
        ],
      ],
    },
  },
});

第二步:建立自訂 <pre> 元件(可選,加複製按鈕用)

rehype-pretty-code 輸出的 code block 是透過 <pre> 標籤包裝的。如果要加複製按鈕或自訂樣式,可以建立一個 Client Component 替換掉預設的 <pre>:

components/MDXPre.tsx
"use client";
import { useRef, useState } from "react";
 
export default function MDXPre(props: React.ComponentPropsWithoutRef<"pre">) {
  const ref = useRef<HTMLPreElement>(null);
  const [copied, setCopied] = useState(false);
 
  const handleCopy = () => {
    const text = ref.current?.querySelector("code")?.innerText ?? "";
    navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };
 
  return (
    <div className="relative group">
      <pre ref={ref} {...props} />
      <button
        onClick={handleCopy}
        className="absolute top-3 right-3 opacity-0 group-hover:opacity-100 transition"
      >
        {copied ? "已複製" : "複製"}
      </button>
    </div>
  );
}

接著在 lib/posts.ts 的 compileMDX 裡把 pre 替換掉:

lib/posts.ts
import MDXPre from "@/components/MDXPre";
 
const { content } = await compileMDX({
  source: mdxContent,
  components: {
    pre: MDXPre,  // ← 用自訂元件替換預設的 <pre>
  },
  options: { /* ... */ },
});

第三步:在 app/globals.css 加入 code block 基礎樣式

keepBackground: false 讓背景色由 CSS 控制,需要自己加上 code block 的樣式:

app/globals.css
/* 程式碼區塊外框 */
.prose pre {
  border-radius: 0.5rem;
  border: 1px solid #e5e7eb;
  overflow-x: auto;
  padding: 1rem 1.25rem;
  font-size: 0.875em;
}
 
/* 暗色模式 */
html.dark .prose pre {
  background-color: #161b22;
  border-color: #30363d;
}

完成以上三步,code block 就會有完整的語法高亮效果。


在文章中寫 Code Block

在 MDX 文章中,只需要正常寫 Markdown code block,並在開頭指定語言:

TypeScript:

function greet(name: string) {
  return `Hello, ${name}!`;
}

Bash:

npm install next-mdx-remote

不同語言會有不同的高亮效果,語言標籤同時也影響 rehype-pretty-code 顯示的標示文字。


進階功能

rehype-pretty-code 還有一些實用的進階功能。

標示指定行數

在語言標籤後面加上 {N},N 是要高亮的行號,例如:

```ts {2}
function greet() {
  console.log("hello") // ← 這行會被標示
}
```

效果如下:

function greet() {
  console.log("hello")
}

要讓高亮生效,globals.css 還需要加上對應 [data-highlighted-line] 的樣式(詳見第三步設定)。

顯示檔名

在語言標籤後面加上 title="檔名",例如:

```ts title="lib/utils.ts"
export function formatDate(date: string) {
  return new Date(date).toLocaleDateString("zh-TW");
}
```

效果如下:

lib/utils.ts
export function formatDate(date: string) {
  return new Date(date).toLocaleDateString("zh-TW");
}

要讓 title 欄生效,globals.css 還需要加上 figcaption[data-rehype-pretty-code-title] 的樣式(詳見第三步設定)。


主題設定

rehype-pretty-code 支援同時設定暗色和亮色主題,搭配 CSS 變數切換:

[rehypePrettyCode, {
  theme: {
    dark: "github-dark",
    light: "github-light",
  },
  keepBackground: false, // 背景色交給 CSS 控制
}]

keepBackground: false 的好處是讓 code block 的背景色由你自己的 CSS 控制,方便統一整個網站的配色。


小結

使用 Shiki + rehype-pretty-code 的好處是:

  • 高亮品質接近 VS Code,效果精準
  • 與 Next.js + MDX 整合良好,設定簡單
  • 支援暗色 / 亮色雙主題
  • 進階功能(行高亮、檔名、diff)都有內建

對技術 Blog 來說幾乎是必備組合,強烈推薦。

下一篇會繼續介紹這個 Blog 的 TOC 目錄是怎麼做的。

分享:XLinkedIn
← 上一篇我是如何用 Next.js 打造這個技術 Blog
下一篇 →在 Next.js 使用 MDX 撰寫技術文章