Tech
Next.js
【Next.js】MDX のコードブロックにシンタックスハイライトを適用する方法(コピー機能付き)
2025年9月21日
2025年9月21日

こんにちは、けいこんぐらです!
今回は、Next.js
で MDX
のコードブロックにシンタックスハイライトを適用する方法について解説します。
実装方法の記事があまりなくて、なかなか苦労したので備忘録も兼ねて書いております、、
↓↓ 実現したいのは、いろんな技術記事でよく見かけるこれです 🔥
const greeting = "Hello World";
console.log(greeting);
本ブログは Next.js で構成されており、記事部分には MDX を使用しています。
同じような構成で、自分のブログにコードブロックを実装したい方に向けて、私がどのように実装したかの参考になれば幸いです!⭐️
使用技術
- Next.js
- 本ブログは
15.5.2
を使用しています Turbopack
は使用していません
- 本ブログは
- MDX
- Next.js での詳細な使用方法は こちら をご覧ください
- Tailwind CSS
- shadcn/ui
- rehype-pretty-code(今回の目玉 👀)
- その他プラグイン
実装手順
まずは Next.js 公式の手順通りに MDX を導入します。
npm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
MDX をきれいに表示するツールたちとシンタックスハイライトを適用するために、以下のパッケージをインストールします。
プラグイン | 役割 |
---|---|
rehype-pretty-code | シンタックスハイライト |
remark-gfm | GitHub Flavored Markdown |
react-children-utilities | React の子要素を操作する |
@tailwindcss/typography | Tailwind CSS の Typography プラグインで、MDX のスタイル調整 |
npm install rehype-pretty-code remark-gfm react-children-utilities
npm install -D @tailwindcss/typography
next.config.ts
を next.config.mjs
に変更し、以下のように設定します。
設定できるテーマ一覧 → Themes
import createMDX from "@next/mdx";
import rehypePrettyCode from "rehype-pretty-code";
import remarkGfm from "remark-gfm";
/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx"],
};
/** @type {import('rehype-pretty-code').Options} */
const options = {
// 🙆♂️ ここでテーマを指定できる
theme: "dark-plus",
};
const withMDX = createMDX({
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [[rehypePrettyCode, options]],
},
});
export default withMDX(nextConfig);
プロジェクトルートに mdx-components.tsx
を作成します。
import type { MDXComponents } from "mdx/types";
const components: MDXComponents = {};
export function useMDXComponents(): MDXComponents {
return components;
}
忘れてはいけないのが Tailwind CSS の Typography プラグインの設定です ⚠️
@import "tailwindcss";
@import "tw-animate-css";
@plugin "@tailwindcss/typography";
...省略
// 親要素に "prose" クラスを追加するとMDX要素がキレイに表示される!
...省略
return (
<html lang="ja">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<div className="prose">{children}</div>
</body>
</html>
);
これでとりあえずは、コードブロックにシンタックスハイライトが適用されるようになります!
これが、
```ts title="sample.ts"
const greeting = "Hello, Next.js with MDX!";
```
こうなる!いいですね 💯
あとは、mdx-components.tsx でコードブロックのスタイルを調整したり、コピー機能を追加したりしていきます。
まずは、コピーボタンを作ります!
ボタンがクリックされたら、props で渡されたテキストをクリップボードにコピーし、2 秒間チェックマークを表示するようなコンポーネントです。
"use client";
import { Check, Copy } from "lucide-react";
import { useState } from "react";
import { cn } from "@/lib/utils";
// shadcn/ui の Button コンポーネントを使用しています
import { Button } from "./ui/button";
export default function CopyButton({
text,
className,
}: {
text: string;
className?: string;
}) {
const [isOk, setIsOk] = useState(false);
return (
<Button
size="icon"
variant="ghost"
className={cn("relative hover:bg-accent/10", className)}
onClick={() => {
setIsOk(true);
setTimeout(() => setIsOk(false), 2000);
navigator.clipboard.writeText(text);
}}
>
<Check
className={cn(
"-translate-x-1/2 -translate-y-1/2 absolute top-1/2 left-1/2",
"text-muted-foreground transition-opacity duration-300",
isOk ? "opacity-100" : "opacity-0"
)}
/>
<Copy
className={cn(
"-translate-x-1/2 -translate-y-1/2 absolute top-1/2 left-1/2",
"text-muted-foreground transition-opacity duration-300",
isOk ? "opacity-0" : "opacity-100"
)}
/>
<span className="sr-only">コピー</span>
</Button>
);
}
あとはコードブロックで使用される要素をカスタマイズしていきます!(タイトルの装飾とコピーボタンの配置です)
import type { MDXComponents } from "mdx/types";
// onlyText は React の子要素からテキストだけを抽出するユーティリティ
import { onlyText } from "react-children-utilities";
import CopyButton from "./components/copy-button";
export const components = {
figcaption: (props) => (
<figcaption
className="w-fit rounded-t-sm bg-primary px-3 py-1 text-primary-foreground text-xs"
{...props}
/>
),
pre: (props) => {
return (
<div className="relative">
<pre
className="mt-0 rounded-sm rounded-tl-none"
{...props}
tabIndex={-1}
/>
<CopyButton
text={onlyText(props.children)}
className="absolute top-1 right-1"
/>
</div>
);
},
} satisfies MDXComponents;
export function useMDXComponents(): MDXComponents {
return components;
}
これで完璧です!よく見るやつですね!!🎉
おわりに
今回は、Next.js で MDX のコードブロックにシンタックスハイライトを適用する方法について解説しました。
コードブロックを実装するのはまあまあめんどくさいですが、一度実装してしまえば使い回せますし、サイトの見栄えもかなり良くなるので、「いいな」とか「これほしかった!」と思った方はぜひ導入してみてください 🔥
また、rehype-pretty-code
は他にもいろんな機能があるので、興味がある方は 公式ドキュメント をご覧ください。
- 横スクロール
- 行番号
- ハイライト行の指定 など