跳至內容
Fumadocs

內建搜尋

Fumadocs 的內建文件搜尋

Fumadocs 透過 ZBSearch 支援文件搜尋。這不僅是預設選項,也是我們推薦的選項,因為它可以自行託管,而且完全免費。

設定

架設伺服器以處理搜尋請求。

從來源建立

從來源物件建立伺服器。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

export const { GET } = createFromSource(source);

從搜尋索引建立

從搜尋索引建立伺服器,每個索引都必須包含 structuredData 欄位。

此欄位通常由您的內容來源 (例如 Fumadocs MDX) 提供。您也可以使用 Remark Structure 外掛,從 Markdown/MDX 文件中擷取。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createSearchAPI } from 'fumadocs-core/search/server';

export const { GET } = createSearchAPI('advanced', {
  indexes: source.getPages().map((page) => ({
    title: page.data.title,
    description: page.data.description,
    url: page.url,
    id: page.url,
    structuredData: page.data.structuredData,
  })),
});

搜尋文件

您可以透過以下方式搜尋文件:

  • Fumadocs UI:已內建支援,詳情請參閱搜尋 UI。
  • 搜尋用戶端:
import {  } from 'fumadocs-core/search/client';

const { , , ,  } = ();

屬性

型別

設定

標籤篩選

支援依標籤篩選結果,適合用來實作類似本文件網站的多文件架構。

import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

const server = createFromSource(source, {
  buildIndex(page) {
    return {
      title: page.data.title,
      description: page.data.description,
      url: page.url,
      id: page.url,
      structuredData: page.data.structuredData,
      // 使用您想要的值,例如 page.slugs[0]
      tag: '<value>',
    };
  },
});

並更新您的搜尋用戶端:

  • Fumadocs UI:在搜尋 UI 中設定標籤篩選。
  • 搜尋用戶端:將標籤傳入 useFetchSearch()。
import { useFetchSearch } from 'fumadocs-core/search/client';

const { search, onSearchChange, isLoading, data } = useFetchSearch({
  tag: '<value>', 
});

靜態模式

若要支援靜態網站,請使用搜尋伺服器提供的 staticGET,並將該路由設為靜態或預先算繪。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

// 靜態快取
export const revalidate = false;
export const { staticGET: GET } = createFromSource(source);

createSearchAPI 也提供 staticGET。

接著更新您的搜尋用戶端:

  • Fumadocs UI:在搜尋 UI 中使用靜態用戶端。

  • 搜尋用戶端:改用 useStaticSearch() 取代 useFetchSearch()。

    import { useStaticSearch } from 'fumadocs-core/search/client';
    
    const { search, onSearchChange, isLoading, data } = useStaticSearch();

    屬性

    型別

請注意

靜態搜尋需要用戶端下載匯出的搜尋索引。 對大型文件網站而言,成本可能相當高。

在這種情況下,建議您改用 Orama Cloud 或 Algolia 等雲端解決方案。

國際化

搜尋功能開箱即支援所有語言:預設的 multilingual 模式採用 Unicode 斷詞,因此所有語系 (包括中文和日文) 都共用同一個搜尋資料庫,完全不需要任何設定。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

// i18n 不需要額外設定
const server = createFromSource(source);

並更新您的搜尋用戶端:

  • Fumadocs UI:無需任何變更,只要正確設定 i18n,Fumadocs UI 就會自動處理。
  • 搜尋用戶端: 在搜尋用戶端加上 locale,這樣使用者就只能搜尋到指定語系的頁面。
import { useFetchSearch } from 'fumadocs-core/search/client';

const { search, onSearchChange, isLoading, data } = useFetchSearch({
  locale: 'cn',
});

這同樣適用於靜態模式,只需改為將 locale 傳入 useStaticSearch() 即可。

特定語言的分詞

multilingual 模式不會套用特定語言的詞幹提取 (stemming) 或停用詞 (stop-words) 。 若未進行詞幹提取,像 recordings 這樣的複數查詢就無法比對到包含 recording 的頁面。

若要加入詞幹提取器,同時保留多語言斷詞與單一資料庫,請傳入 tokenizer:

import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { stemmer } from '@zbsearch/stemmers/english';

const server = createFromSource(source, {
  tokenizer: { language: 'multilingual', stemming: true, stemmer }, 
});

或者,您也可以透過 localeMap,為每個語系指定支援語言清單中的語言:

import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

const server = createFromSource(source, {
  localeMap: {
    // [語系]: 搜尋選項
    ru: { language: 'russian' },
    en: { language: 'english' },
  },
});

請注意,啟用 localeMap 後,系統會為每個語系各建立一個獨立的搜尋資料庫。

靜態模式

自訂的 tokenizer 也必須提供給用戶端,因為用戶端需要以相同方式對查詢進行分詞。 請透過 useStaticSearch() 的 initDB 傳入。

無頭式

您也可以將搜尋伺服器架設在其他後端,例如 Express 或 Elysia。

import { initAdvancedSearch } from 'fumadocs-core/search/server';

const server = initAdvancedSearch({
  // 您仍需傳入索引
});

server.search('query', {
  // 您可以在此指定 `locale` 與 `tag`
});

How is this guide?

最後更新於