跳至內容
Fumadocs

createGraphQLPage()

用於算繪 GraphQL 文件內容的元件

概覽

Fumadocs GraphQL 使用 <GraphQLPage /> 元件來算繪頁面內容,此元件應為用戶端元件。

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  // 設定
});

互動測試區

設定端點後,operation 頁面會提供互動測試區:讀者可以編輯 operation、透過表單或 JSON 填入變數,再附上自己的標頭送出。

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  playground: {
    url: 'https://api.example.com/graphql',
    // 允許使用者編輯端點 URL(預設:true)
    allowUrlEdit: false,
    // 互動測試區請求的預設標頭
    headers: {
      'X-Client-Name': 'docs',
    },
  },
});

請勿將密鑰等機密資訊放入 headers,因為這些內容會傳送至瀏覽器、顯示在程式碼範例中,並依端點來源保存在瀏覽器的本機儲存空間 (local storage) 中。

查詢 (query) 與變更 (mutation) 會透過 HTTP POST 傳送,您可以替換其 fetcher,例如透過代理伺服器轉送請求:

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  playground: {
    async fetcher(request) {
      const start = performance.now();
      const res = await fetch('/api/proxy', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...request.headers },
        body: JSON.stringify({ query: request.query, variables: request.variables }),
      });

      return {
        type: 'response',
        status: res.status,
        time: performance.now() - start,
        body: await res.text(),
        contentType: res.headers.get('Content-Type') ?? '',
        // 選填,會顯示在 Headers 頁籤中
        headers: Array.from(res.headers),
      };
    },
  },
});

或者,您也可以使用 render 完全替換互動測試區的 UI,它會顯示在原本簽章列的位置:

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  playground: {
    render({ kind, name, operation }) {
      return <div>my playground</div>;
    },
  },
});

訂閱

在訂閱頁面上,互動測試區會訂閱 subscriptionUrl,並記錄收到的事件。預設值為將 url 的 scheme 改為 ws(s):// 後的網址。

subscriptionUrl協定
ws://, wss://graphql-ws (graphql-transport-ws)
http://, https://GraphQL over SSE (distinct connections 模式)
components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  playground: {
    url: 'https://api.example.com/graphql',
    // 在同一個端點上透過 SSE 使用 GraphQL(GraphQL over SSE)
    subscriptionUrl: 'https://api.example.com/graphql',
  },
});

瀏覽器限制

瀏覽器無法設定 WebSocket 連線的標頭,因此 graphql-ws 改將標頭放在 connection_init 的酬載中傳送。

程式碼範例

範例請求會以 GraphQL 呈現,或以 cURL、JavaScript、Go、Python、Java、C# 和 Rust 程式碼呈現,這些程式碼會帶上 playground.headers,將請求傳送至 playground.url (未設定時會使用預留位置) 。互動測試區也會針對正在編輯的請求顯示相同的程式碼。訂閱頁面的範例僅以 GraphQL 呈現。

您可以透過 codeUsages 新增產生器,或移除預設的產生器:

components/api-page.tsx
'use client';
import {
  createCodeUsageGeneratorRegistry,
  createGraphQLPage,
  registerDefaultCodeUsages,
} from '@fumadocs/graphql/ui';

// 若要從零開始,請省略預設項目
const codeUsages = registerDefaultCodeUsages(createCodeUsageGeneratorRegistry());

// 預設項目:curl、js、go、python、java、csharp、rust
codeUsages.remove('java');
codeUsages.add('graphql-request', {
  label: 'graphql-request',
  lang: 'js',
  generate({ url, query, variables = {}, headers }) {
    return `import { request } from 'graphql-request';

const data = await request(${JSON.stringify(url)}, ${JSON.stringify(query)}, ${JSON.stringify(variables)}, ${JSON.stringify(headers)});`;
  },
});

export const GraphQLPage = createGraphQLPage({ codeUsages });

屬性

型別

交互連結

型別頁面會自動互相連結,也會連結至 operation。Operation 頁面則會讓讀者留在原頁面,其中的型別會在結構描述 UI 中開啟。

您也可以自行解析這些連結:

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  typeLinks(name) {
    return `/docs/types/${name}`;
  },
  operationLinks(kind, name) {
    return `/docs/${kind}/${name}`;
  },
});

若型別或 operation 沒有獨立頁面,請回傳 undefined。

自訂版面配置

您可以自訂 operation 頁面與型別頁面的版面配置。

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  content: {
    renderOperationLayout(slots) {
      return (
        <div className="flex flex-col gap-6">
          {slots.header}
          {slots.playground}
          {slots.description}
          {slots.deprecated}
          {slots.arguments}
          {slots.returns}
          {slots.example}
        </div>
      );
    },
  },
});
Slot算繪內容
header標題,僅在包含多個項目的頁面上顯示
playground簽章 (例如 QUERY customer(id: ID!): Customer) 、其指示詞以及互動測試區
descriptionoperation 的說明
deprecated棄用原因
arguments引數
returns回傳型別及其欄位
example範例請求與回應,在寬版頁面上會顯示於 operation 旁

結構描述 UI

自訂型別的算繪方式。

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  schemaUI: {
    render(options, ctx) {
      // 完全自訂的 schema 算繪器
      return <ctx.SchemaUI {...options} />;
    },
  },
});

國際化

假設您已在 UI 層級設定好國際化:

layout.shared.tsx
import { defineI18n } from 'fumadocs-core/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import { graphqlTranslations } from '@fumadocs/graphql/i18n';

const i18n = defineI18n({
  languages: ['en', 'cn'],
  defaultLanguage: 'en',
});

export const translations = i18n
  .translations()
  .extend(uiTranslations())
  .extend(graphqlTranslations())
  .add({
    cn: {
      displayName: 'Chinese',
      'Arguments(operation page)': '参数',
    },
  });

詳細資訊請參閱翻譯。

語法突顯

GraphQL 頁面會使用 Shiki 為程式碼區塊進行語法突顯,若要自訂,可以傳入語法突顯器。

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
import { highlighter } from '@/lib/highlighter';

export const GraphQLPage = createGraphQLPage({ highlighter });

自訂元件

覆寫預設的標題、程式碼區塊及 Markdown 元件。

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  components: {
    Heading({ id, depth, ...props }) {
      const Tag = `h${depth}` as const;
      return <Tag id={id} {...props} />;
    },
    CodeBlock({ lang, code }) {
      return <pre data-lang={lang}>{code}</pre>;
    },
  },
});

自訂 UI

若現有選項無法滿足您的自訂需求,您可以透過 Fumadocs CLI 將 UI 安裝到您的程式碼庫中。

完整 UI

GraphQL 頁面的完整 UI,以無頭式層為基礎建構而成。

npx @fumadocs/cli add graphql/page

它會自行安裝 <GraphQLPage />,因此不再需要 components/api-page.tsx。請更新 <GraphQLPage /> 的匯入路徑:

import { GraphQLPage } from '@/components/api-page'; 
import { GraphQLPage } from '@/components/graphql/page'; 

部件

只需安裝您想編輯的部件,再透過 components 傳回即可。components 中沒有互動測試區的 slot:它會由已安裝的 graphql/operation 算繪,您也可以從 playground.render 回傳 <OperationPlayground />。

元件內容
graphql/operationoperation,包含其引數與範例
graphql/type-docs具名型別,包含其欄位與使用之處
graphql/schema-ui型別、引數與欄位的詳細資訊
graphql/playground互動測試區
components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
import { Operation } from '@/components/graphql/operation';
import { TypeDocs } from '@/components/graphql/type-docs';

export const GraphQLPage = createGraphQLPage({
  components: {
    Operation,
    TypeDocs,
  },
});

How is this guide?

最後更新於