跳至內容
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 大致相同。

使用巨集定義集合時,您仍可保留 source.config.ts,用來設定全域選項與外掛。

瀏覽器

巨集集合也能在瀏覽器中使用。只要在用戶端元件中匯入集合,再透過 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>
  );
}

若頁面使用路徑參數,請從載入器傳入其參數:docs.getPage(page.path, page.params)。

瀏覽器會執行您匯入 docs 的來源模組的完整內容。若您的 loader() 包含僅限伺服器端的 來源 (例如 openapi.staticSource()) ,請將集合定義在另一個模組中 (例如 lib/collections.ts) ,再從該模組匯入。

Async 集合

啟用 async 後,只有 frontmatter 會預先打包,內容則會隨需擷取。

body 的運作方式相同,只是它會暫停 (suspend) ,直到內容可用為止。以下兩個額外的方法可控制此行為:

  • 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 可限制哪些模組能使用它,傳入 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 的範圍。

限制

巨集呼叫會以靜態方式編譯,請留意以下規則:

  • 每個呼叫都必須指派給頂層的 const (變數名稱用來識別集合) :

    // ✓
    const docs = defineDocs({ dir: 'content/docs' });
    
    // ✗ 不支援
    export function create() {
      return defineDocs({ dir: 'content/docs' });
    }
  • 會影響內容打包方式的選項 (dir、files、async) 必須能被靜態分析 (即字串/布林值字面值) 。動態邏輯請改放在 schema 或 mdxOptions 等選項中。

  • Macro API 目前尚不支援 dynamic 集合。如需延遲載入,建議改用 async。

  • 不支援從 fumadocs-mdx/macro 重新匯出。

How is this guide?

最後更新於