コンテンツへスキップ
Fumadocs

Macro API

fumadocs-mdx/macro を使って、アプリ内でコレクションを定義します。

概要

fumadocs-mdx/macro を使用すると、アプリケーションのモジュール内でコレクションを直接宣言できます。

バンドラー(またはランタイムのローダー)が、defineDocs / defineCollections をコンテンツファイルのインポートにコンパイルします。

  • コード生成は不要です。
  • source.config.ts も不要です。

使い方

import { defineDocs } from 'fumadocs-mdx/macro';
import { loader } from 'fumadocs-core/source';

export const docs = defineDocs({
  dir: 'content/docs',
});

export const source = loader({
  baseUrl: '/docs',
  source: docs.toFumadocsSource(),
});

コレクションのオプションは、config API とほぼ同じです。

Macro でコレクションを定義する場合でも、グローバルオプションやプラグインの設定用に source.config.ts を残しておくことができます。

ブラウザ

Macro コレクションはブラウザでも動作します。クライアントコンポーネントでコレクションをインポートし、body でエントリーをレンダリングするだけで、クライアントローダーは必要ありません。

import { docs } from '@/lib/source';

export default function Page({ path }: { path: string }) {
  const page = docs.getPage(path);
  if (!page) return <div>Not Found</div>;

  const MDX = page.body;

  return (
    <div className="prose">
      <h1>{page.title}</h1>
      <MDX />
    </div>
  );
}

パスパラメータを持つページでは、ローダーから取得した params を渡してください:docs.getPage(page.path, page.params)。

docs のインポート元のモジュールは、ブラウザ上ですべて実行されます。loader() に openapi.staticSource() のような サーバー専用のソースが含まれる場合は、コレクションを別のモジュール(例: lib/collections.ts)で定義し、そこからインポートしてください。

非同期コレクション

async を有効にすると、事前にバンドルされるのはフロントマターのみで、コンテンツはオンデマンドで取得されます。

body も同様に動作しますが、コンテンツが利用可能になるまでサスペンドする点が異なります。この挙動は、次の2つの追加メソッドで制御できます。

  • preload() はレンダリング前にコンテンツを読み込むため、body はサスペンドせずにレンダリングされます。ルートローダー内で呼び出してください。
  • load() は toc など、読み込まれたコンテンツを返します。返される Promise はキャッシュされるため、レンダリング中に呼び出しても問題ありません。
import { use } from 'react';
import { docs } from '@/lib/source';

// ルートローダー内で実行(React Router、TanStack Start)
export async function loader({ path }: { path: string }) {
  await docs.getPage(path)?.preload();
  return { path };
}

export default function Page({ path }: { path: string }) {
  const page = docs.getPage(path);
  if (!page) return <div>Not Found</div>;

  const { toc } = use(page.load());
  const MDX = page.body;

  return (
    <div className="prose">
      <h1>{page.title}</h1>
      <MDX />
    </div>
  );
}

コンテンツは遅延読み込みされるため、プリロードしていない場合は、ページを <Suspense> バウンダリでラップしてください。

設定

Macro API はデフォルトで有効です。macro を渡すと Macro API を使用できるモジュールを制限でき、false を渡すと無効にできます。React Router と TanStack Start では、Vite プラグインに渡してください。

next.config.mjs
import { createMDX } from 'fumadocs-mdx/next';

const withMDX = createMDX({
  macro: {
    // プロジェクトルートからの相対 glob パターン
    include: ['lib/**/*.ts', 'lib/**/*.tsx'],
  },
  // または、完全に無効化する場合:
  // macro: false,
});

デフォルトでは、すべての JS/TS モジュールが対象になります (node_modules は常に除外されます) 。特定のパスにのみ変換を適用したい場合は、include で対象を絞り込んでください。

制約

Macro の呼び出しは静的にコンパイルされます。以下のルールに注意してください。

  • 各呼び出しはトップレベルの const に代入してください (変数名によってコレクションが識別されます) 。

    // ✓
    const docs = defineDocs({ dir: 'content/docs' });
    
    // ✗ サポートされていません
    export function create() {
      return defineDocs({ dir: 'content/docs' });
    }
  • コンテンツのバンドル方法を決めるオプション (dir、files、async) は、静的に解析できる値 (文字列 / 真偽値のリテラル) にする必要があります。動的なロジックは、schema や mdxOptions などのオプション側に記述してください。

  • dynamic コレクションは、Macro API ではまだサポートされていません。遅延読み込みには async の使用をおすすめします。

  • fumadocs-mdx/macro からの再エクスポートはサポートされていません。

How is this guide?

最終更新日