# Fumadocs MDX (the built-in content source): Macro API
URL: /ja/docs/mdx/macro
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/mdx/macro.ja.mdx

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

## 概要 [#overview]

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

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

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

## 使い方 [#usage]

```ts tab="lib/source.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(),
});
```

```ts tab="lib/blog.ts"
import { defineCollections } from 'fumadocs-mdx/macro';
import { loader } from 'fumadocs-core/source';

const blog = defineCollections({
  type: 'doc',
  dir: 'content/blog',
});

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

コレクションのオプションは、[config API](/docs/mdx/collections) とほぼ同じです。

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

### ブラウザ [#browser]

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

```tsx
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>
  );
}
```

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

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

#### 非同期コレクション [#async-collections]

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

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

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

```tsx
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>` バウンダリでラップしてください。

## 設定 [#configuration]

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

```js tab="Next.js" title="next.config.mjs"
import { createMDX } from 'fumadocs-mdx/next';

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

```ts tab="Vite" title="vite.config.ts"
import { fumadocsMdx } from 'fumadocs-mdx/vite';

export default {
  plugins: [
    fumadocsMdx({
      macro: {
        include: ['src/**/*.ts', 'src/**/*.tsx'],
      },
    }),
  ],
};
```

```ts tab="Waku" title="waku.config.ts"
import { defineConfig } from 'waku/config';
import { fumadocsMdx } from 'fumadocs-mdx/vite';

export default defineConfig({
  vite: {
    plugins: [
      fumadocsMdx({
        macro: {
          include: ['src/**/*.ts', 'src/**/*.tsx'],
        },
      }),
    ],
  },
});
```

```js tab="Node.js"
import { register } from 'fumadocs-mdx/node';

register({
  macro: {
    include: ['lib/**/*.ts'],
  },
});
```

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

### 制約 [#constraints]

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

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

  ```ts
  // ✓
  const docs = defineDocs({ dir: 'content/docs' });

  // ✗ サポートされていません
  export function create() {
    return defineDocs({ dir: 'content/docs' });
  }
  ```

* コンテンツのバンドル方法を決めるオプション (`dir`、`files`、`async`) は、静的に解析できる値 (文字列 / 真偽値のリテラル) にする必要があります。動的なロジックは、`schema` や `mdxOptions` などのオプション側に記述してください。

* [`dynamic`](/docs/mdx/async#dynamic-mode) コレクションは、Macro API ではまだサポートされていません。遅延読み込みには [`async`](/docs/mdx/async) の使用をおすすめします。

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