MDX の紹介と導入【Next.js】
はじめに
先日、Next.js の勉強会で、MDX の実装について取り上げました 🫐
Markdown の書きやすさと、React コンポーネントの柔軟性を、
両方活かせる MDX は、筆者が個人的に好きな技術の1つでもあります!
今回は、MDX について調査したので、基礎的な内容をまとめました!
時間の節約になれば、嬉しいです 🙌
MDX とは?
MDX とは、Markdown の中で React コンポーネントを使えるようにした形式です。
通常の Markdown では、テキストの装飾や構造化は可能ですが、
インタラクティブな要素や複雑な UI コンポーネントを埋め込むことは困難でした。
MDX を使うことで、以下のような利点があります:
- Markdown の書きやすさを保ちながら、React コンポーネントが使える
- 文章の中にインタラクティブなデモを埋め込める
- 既存の React コンポーネントライブラリを活用できる
- TypeScript との相性も良好
例えば、以下のように書くことができます:
src/app/sample/page.mdx
# 私のブログ記事
これは普通の **Markdown** のテキストです。
<MyComponent title="Hello World" />
そして、また Markdown に戻ります。
技術記事やドキュメント、ブログなどで、
表現力豊かなコンテンツを作成できるのが、MDX の最大の特徴です!
Next.js で MDX を使う方法は?
Next.js で、MDX を使用する際の選択肢は、いくつかあります。
有力なのは、:
- @next/mdx: Next.js が公式にサポートする方法で、ローカルの MDX ファイルを直接ページとして使用できる
- next-mdx-remote-client: リモートの MDX コンテンツを効率的に処理できるライブラリ
- mdx-bundler: ビルド時に MDX をバンドルするためのライブラリ
今回の記事では、
より柔軟で実用的な next-mdx-remote-client
を紹介していきます!
next-mdx-remote-client とは?
next-mdx-remote-client
は、Next.js アプリケーションでリモートの MDX コンテンツを読み込むためのライブラリです。
データベースや CMS、外部 API などから取得した MDX コンテンツを、
Next.js アプリケーション内で、安全にレンダリングすることができます!
next-mdx-remote
について
📝 メモ:以前使われていた 実は、以前まで next-mdx-remote というライブラリが広く使われていました。
しかし、next-mdx-remote は長い間メンテナンスされておらず、
MDX v3 への対応や App Router での安定性に課題がありました。
そこで登場したのが next-mdx-remote-client
です!
next-mdx-remote-client の特徴
next-mdx-remote-client
は、next-mdx-remote
のフォークとして開発され、
Next.js の公式ドキュメントでも、推奨されているライブラリです!
主な特徴は、以下の通りです:
- MDX v3 完全サポート
- App Router と Pages Router 両方に対応
- 内蔵エラーハンドリング機能
- import/export 文のサポート
- frontmatter の簡単な取得
- 目次(TOC)作成の簡易化
Next.js への導入
さて、基本的な概念を理解したところで、
Next.js への具体的な導入手順を確認してみましょう!
1. ライブラリのインストール
npm install next-mdx-remote-client
2. App Router での基本的な使用方法
// app/blog/[slug]/page.tsx
import { MDXRemote } from "next-mdx-remote-client/rsc";
// MDX コンテンツ(通常は外部ファイルから取得)
const mdxSource = `
# Hello MDX!
これは **MDX** で書かれたコンテンツです。
<CustomButton onClick={() => alert('クリック!')}>
ボタンをクリック
</CustomButton>
`;
// カスタムコンポーネント
const CustomButton = ({ children, onClick }) => (
<button
onClick={onClick}
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
>
{children}
</button>
);
export default function BlogPost() {
return (
<div className="prose mx-auto">
<MDXRemote source={mdxSource} components={{ CustomButton }} />
</div>
);
}
3. ファイルから MDX を読み込む場合
// app/blog/[slug]/page.tsx
import { readFile } from "fs/promises";
import { join } from "path";
import { MDXRemote } from "next-mdx-remote-client/rsc";
export default async function BlogPost({ params }) {
// ファイルシステムから MDX を読み込み
const filePath = join(process.cwd(), "content", `${params.slug}.mdx`);
const mdxSource = await readFile(filePath, "utf-8");
return (
<div className="prose mx-auto">
<MDXRemote
source={mdxSource}
components={{
// カスタムコンポーネントをここで定義
h1: (props) => <h1 className="text-4xl font-bold mb-4" {...props} />,
p: (props) => <p className="mb-4 leading-relaxed" {...props} />,
}}
/>
</div>
);
}
4. frontmatter の活用
import { MDXRemote } from "next-mdx-remote-client/rsc";
export default async function BlogPost({ params }) {
const mdxSource = `---
title: "MDX の使い方"
date: "2024-01-01"
author: "Developer"
---
# {frontmatter.title}
投稿日: {frontmatter.date}
著者: {frontmatter.author}
これは MDX のサンプルです。
`;
return (
<div className="prose mx-auto">
<MDXRemote
source={mdxSource}
options={{
parseFrontmatter: true,
}}
/>
</div>
);
}
このシンプルなコードで、Markdown の書きやすさと React コンポーネントの柔軟性を
両方活かしたコンテンツが作成できます!
なぜ MDX なのか?
個人的には、MDX の魅力は、
コンテンツ作成の効率性と表現力の両立にあると、考えています!
MDX を選ぶ理由としては:
- 書きやすさ: Markdown の直感的な記法を保持
- 表現力: React コンポーネントで複雑な UI も表現可能
- 再利用性: 既存のコンポーネントライブラリを活用できる
- メンテナンス性: コンテンツとロジックを適切に分離
- SEO 対応: 最近の SSR/SSG フレームワークとの相性が良い
Web 上に公開するページの大部分を、md 形式で作成しつつ、
ポイントでリッチな UI/UX を導入できるのが、便利です 👍
おわりに
最後まで読んでいただだき、ありがとうございます 🥳
ハンズオン形式で、
実際に手を動かして学習したい場合は、以下の教材もチェックしてみてください!!
この記事が、少しでも参考になれば嬉しいです!
そして、もし、間違いや補足情報などがありましたら、ぜひコメントを追加してください!
Happy Hacking :)
参考
🫐 勉強会紹介:
Discussion
As the creator of the
next-mdx-remote-client package
, I saw your article and really liked it — great work, you explained everything very well. I hopenext-mdx-remote-client
proves useful to many developers, and it makes me happy to know that.Wow, I am honored to get your comment 👋
I really like the next-mdx-remote-client.
It works very well to integrate MDX into the next.js project in a practical way.
Thanks for the best work.
Have a wonderful day ;)