NAOKI KANEKO

MDXでできること、Markdownとの違いを徹底解説


MDXでできること、Markdownとの違いを徹底解説
#Others

このブログでは.mdxと.mdの両方の拡張子を使っている。 見た目はほとんど同じに見えるが、できることには明確な差がある。 この記事では両者の違いを整理した上で、Markdown/MDXの記法を「網羅的に」一覧形式でまとめる。

結論: MDXは「Markdown + JSX(コンポーネント)」

  • .md: 静的なテキストのみ。装飾はMarkdown記法の範囲内に限定される。
  • .mdx: Markdown記法に加えて、Reactコンポーネントをそのまま埋め込める。import文で外部コンポーネントを読み込んだり、{式}でJavaScriptの値を評価したりもできる。

つまり、.mdが「文章を書くための記法」であるのに対し、 .mdxは「文章の中にアプリケーションの一部を持ち込める記法」といえる。

主な違いの一覧

項目.md.mdx
見出し・リスト等の基本記法○○
GFM拡張(表・チェックリスト等)プラグイン次第プラグイン次第
JSXコンポーネントの埋め込み×○
import文×○
JavaScript式の埋め込み({})×○
ビルド時の扱い単なるテキストJSXにコンパイルされるコード
学習コスト低いReactの知識がある程度必要

単純なテキスト記事だけなら.mdで十分だが、 本文中にグラフやインタラクティブなUIを混ぜたい場合は.mdxを選ぶ、という使い分けになる。

Markdown記法一覧

各項目は「書き方(コード)」と「表示結果(実際のレンダリング)」を並べて示す。

見出し

# 見出し1(H1)
## 見出し2(H2)
### 見出し3(H3)
#### 見出し4(H4)
##### 見出し5(H5)
###### 見出し6(H6)

見出しはこの記事内の##・###がまさにその実例である。 数字が小さいほど大きな見出しになる。

文字装飾

*イタリック* または _イタリック_
**太字** または __太字__
***太字イタリック***
~~取り消し線~~(GFM拡張)

表示結果: イタリック / 太字 / 太字イタリック / 取り消し線

リスト

- 箇条書き
* 箇条書き(同じ意味)
+ 箇条書き(同じ意味)
1. 番号付きリスト
2. 番号付きリスト
3. 番号付きリスト

表示結果(ネスト込み):

  • 親項目A
    • 子項目A-1
    • 子項目A-2
  • 親項目B

ネストする場合は半角スペース2〜4個でインデントする。 番号付きリストは開始番号を3.のように変えると、その番号から連番が始まる。

タスクリスト(GFM拡張)

- [ ] 未完了のタスク
- [x] 完了したタスク

表示結果:

  • 執筆
  • 校正

引用

> 引用文
>> 引用の中の引用(二重引用)

表示結果:

Markdownはシンプルであることが最大の価値である。

コード

インラインコードはバッククォート1つで囲む。

`インラインコード`

表示結果: const x = 1;

複数行のコードブロックはバッククォート3つで囲み、言語名を添えるとシンタックスハイライトが効く。

```ts
const x: number = 1;
```

水平線

---
***
___

いずれも同じ意味の区切り線になる(この記事のセクション間にも実際に使用している)。

リンクと画像

[リンクテキスト](https://example.com)
![代替テキスト](/images/example.png)

タイトル属性を付けたい場合は[テキスト](URL "タイトル")のようにURLの後ろに半角スペース+ダブルクォートで追加する。

表(GFM拡張)

| 見出し1 | 見出し2 |
| --- | --- |
| セルA | セルB |
| セルC | セルD |

表示結果:

記法用途
#見出し
-箇条書き
1.番号付きリスト

---の位置にコロンを置くと左寄せ・中央寄せ・右寄せを指定できる(:---, :---:, ---:)。

脚注(GFM拡張)

本文中に脚注を置く場合[^1]。

[^1]: これが脚注の内容。

表示結果として、本文中には[^1]の位置に上付きの番号リンクが挿入され、記事末尾に「Footnotes」という見出しとともに脚注の内容・戻りリンク(↩)がまとめて表示される。

自動リンク(GFM拡張)

URLをそのまま書くと自動的にリンクになる。

https://example.com

エスケープ

記法として解釈させたくない記号はバックスラッシュでエスケープする。

\*これは強調されない\*

表示結果: *これは強調されない*

改行と段落

行末に半角スペースを2つ入れるか、<br />を使うと段落内で改行できる。 何も入れずに1行空けると新しい段落として扱われる。

MDX固有の記法

ここからは.mdxでのみ使える機能。

フロントマター

---
title: "記事タイトル"
date: "2026-01-01"
---

記事のメタデータをファイル先頭に記述する。

実は.mdでもこの部分はgray-matterのようなパーサーで解釈可能で、 必須というわけではないが、慣習的にMDXの記事でもよく使われる。

コンポーネントのimportと埋め込み

import MyChart from "./MyChart";

<MyChart data={data} />

本文中にHTMLタグを書くような感覚で、自作のReactコンポーネントをそのまま配置できる。

JavaScript式の埋め込み

波括弧の中にはJavaScriptの式を直接書ける。

今日は{new Date().getFullYear()}年です。

配列の展開やmap処理

<ul>
  {items.map((item) => (
    <li key={item.id}>{item.name}</li>
  ))}
</ul>

このように、本文の途中にロジックを差し込めるのがMDX最大の特徴である。

コメント

MDXでは、表示に影響しないコメントをJSXの記法で書ける。

{/* これはコメント。表示されない */}

Markdownの標準記法にはコメント構文が存在しないため、これもMDX側の恩恵の1つである。

メタデータのexport

フロントマターとは別に、export文で値を直接エクスポートすることもできる。

export const meta = {
  title: "記事タイトル",
  readingTime: 5,
};

エクスポートした値は、そのMDXファイルをインポートした側のコンポーネントから参照できる。

HTMLタグの直接記述

.mdでもHTMLタグを直接書くことは可能だが、 あくまで「Markdownの中に紛れ込んだ生のHTML文字列」として扱われる。

.mdxでは同じ見た目でも、内部的には正式なJSXとしてパースされる点が異なる。

<div style={{ color: "red" }}>MDXならインラインスタイルもオブジェクトで書ける</div>

.md側ではstyle="color: red"という文字列でしか書けず、{{ }}のようなJavaScriptオブジェクトは使えない。

サニタイズについての注意

このサイトのようにrehype-sanitizeのようなセキュリティ用プラグインを組み込んでいる場合、投稿者以外の第三者が書いたMarkdown/MDXに悪意あるスクリプトが含まれていても、危険なタグや属性は自動的に取り除かれる。裏を返すと、.mdxで自由にコンポーネントを埋め込めるのは「信頼できる書き手が管理するコンテンツ」に限られる、という制約がある。

MDXが向いているケース・向いていないケース

  • 向いている: 記事中にグラフ・スライダー・タブ切り替えなど、Reactコンポーネントとして実装済みのUIをそのまま埋め込みたい場合
  • 向いていない: 第三者が自由に投稿できるCMSのように、実行可能なコードを本文に含めるべきではない場面
  • 迷ったら: まずは.mdで書き始め、後から「コンポーネントを埋め込みたい」という要求が出た時点で.mdxに切り替えても遅くはない

まとめ

  • .mdはシンプルな文章向けで、学習コストが低く安全(実行可能なコードを含まないため)
  • .mdxはMarkdownの読みやすさとReactコンポーネントの表現力を両立できるが、内部的にはコードとしてコンパイルされる
  • 表・チェックリスト・取り消し線・自動リンクなどのGFM拡張は、.md/.mdxどちらでもremark-gfmのようなプラグインを組み込めば利用できる
  • 「文章に埋め込みたいUIやロジックがあるか」が、.mdと.mdxを選ぶ際の判断基準になる