Pagefind 教學:如何為 Eleventy 靜態網站加入純前端搜尋

文章一多,讀者只靠導覽列和分類頁,很難找到幾個月前寫過的文章。這時候先別急著架資料庫,也不用再泡一杯咖啡研究搜尋 API——對靜態網站來說,Pagefind 往往就夠用了。

Pagefind 會在 Eleventy build 完後,把 HTML 編成靜態索引,讓讀者直接在瀏覽器裡搜尋,不需要另外維護搜尋後端。這篇帶你完成最小設定,也會順手排掉繁體中文網站最容易踩到的坑。

Pagefind 適合什麼網站?

Pagefind 不是即時資料庫搜尋,而是「在 build 時建立索引」。因此,個人部落格、文件站和靜態文章站通常很適合;每次文章更新後重新 build,搜尋索引也會一起更新。

你的網站情況 建議
個人部落格、文件站、靜態文章站 使用 Pagefind,設定簡單且不需要搜尋後端
內容放在多個外部來源,而且要即時更新 先評估外部搜尋服務
需要會員權限、個人化結果或即時資料 使用後端或託管搜尋服務
主要內容是繁體中文文章 可以使用 Pagefind,但要先設定正確的 lang 並用實際文章測試

如果你的網站只是讓讀者搜尋已部署的文章,Pagefind 通常已經夠用;不要為了「看起來更專業」就先架一套搜尋伺服器。

開始前要準備什麼?

你需要:

  • 一個可以正常輸出 _site/ 的 Eleventy 專案。
  • 共用 layout 裡有明確的 HTML 語言屬性,例如 <html lang="zh-Hant">
  • 專案可以執行 npx

Pagefind 會在 Eleventy 產生 HTML 後處理輸出目錄,所以先確認單獨執行 Eleventy build 沒有錯誤。

第一步:在 layout 放入搜尋元件

Pagefind 1.5 的 Component UI 會使用索引階段產生的 CSS 和 JavaScript。你可以先把下面內容放在共用 layout,或只放在 /search/ 搜尋頁:

<link rel="stylesheet" href="/pagefind/pagefind-component-ui.css">
<script src="/pagefind/pagefind-component-ui.js" type="module"></script>

<pagefind-modal-trigger></pagefind-modal-trigger>
<pagefind-modal></pagefind-modal>

如果你只想在導覽列放一個搜尋按鈕,可以使用 pagefind-modal-trigger;如果想做獨立搜尋頁,也可以只保留搜尋元件,不必每頁都顯示按鈕。

注意:這些檔案要等 Pagefind 建立索引後才會出現在輸出目錄。因此第一次只看到搜尋框、但 CSS 或 JavaScript 404,通常不是元件寫錯,而是索引還沒產生。

第二步:標示語言和可搜尋內容

在共用 layout 裡設定語言,並把文章正文標成搜尋主體:

<html lang="zh-Hant">
  <body>
    <header data-pagefind-ignore>網站導覽</header>
    <main data-pagefind-body>
      
    </main>
    <footer data-pagefind-ignore>頁尾資訊</footer>
  </body>
</html>

這裡有三個重點:

  1. lang="zh-Hant" 告訴 Pagefind 這是繁體中文內容。
  2. data-pagefind-body 指定真正要搜尋的文章內容。
  3. data-pagefind-ignore 排除選單、頁尾或分享按鈕,避免這些固定文字污染結果。

一旦你在部分頁面使用 data-pagefind-body,沒有這個標記的頁面就不會被索引。因此首頁、分類頁如果也要出現在搜尋結果中,要在那些頁面加入同樣的標記。

第三步:先手動建立索引

Eleventy build 完成後,在專案根目錄執行:

npx -y pagefind --site _site

成功後,_site/ 裡應該會出現 pagefind/ 資料夾,裡面包含瀏覽器需要的索引、CSS 和 JavaScript。

建立索引時,如果終端機出現以下提示,不代表建立失敗:

Pagefind doesn't support stemming for the language zh-hant. Search will still work, but will not match across root words.

這表示 Pagefind 目前不支援 zh-Hant 的 stemming(詞幹還原),因此搜尋仍然可以正常運作,但不會自動將同一個英文詞的不同字形視為相同詞。不要為了消除提示而移除 <html lang="zh-Hant">,實際用繁體中文詞組測試搜尋結果即可。

所謂詞幹還原,是搜尋引擎把同一個詞的不同變化還原成共同的「詞幹」後再比對。例如搜尋 connect 時,啟用 stemming 可能也會找到 connectedconnectingzh-Hant 不支援這項功能,不代表中文搜尋失效;只是 Pagefind 不會自動處理這類英文詞形變化。

不要直接用 file:// 開啟 HTML 測試,改用 Pagefind 提供的測試伺服器:

npx -y pagefind --site _site --serve

接著用瀏覽器開啟它提供的網址,搜尋一個確定存在的文章標題,再測試一個繁體中文詞組,例如「網站安全」。

--serve 只是本機測試用的靜態伺服器,不是正式環境需要部署的搜尋後端。

第四步:讓每次 build 都自動更新

最簡單的方式是在 package.json 把 Eleventy 和 Pagefind 串起來:

{
  "scripts": {
    "build": "eleventy && pagefind --site _site"
  }
}

這樣每次執行 npm run build 時,會先產生最新 HTML,再根據最新內容建立搜尋索引。

如果你希望從 Eleventy 設定檔取得實際輸出目錄,也可以使用 eleventy.after

import { execFile } from "node:child_process";
import { promisify } from "node:util";

const run = promisify(execFile);

export default function (eleventyConfig) {
  eleventyConfig.on("eleventy.after", async ({ directories }) => {
    await run("npx", ["-y", "pagefind", "--site", directories.output]);
  });
}

在 CI 或主機商的 build 環境中,記得確認 npx 可以下載 Pagefind,或改用專案中已鎖定的執行方式。

繁體中文搜尋驗收清單

部署前,依序確認:

  • [ ] Eleventy build 成功。
  • [ ] _site/pagefind/ 存在。
  • [ ] 正式網址能載入 /pagefind/ 下的 CSS、JavaScript 和索引檔。
  • [ ] 搜尋一篇確定存在的文章標題,有回傳結果。
  • [ ] 搜尋「網站安全」等繁體中文詞組,有回傳合理結果。
  • [ ] 導覽列和頁尾文字沒有變成每篇文章的搜尋關鍵字。
  • [ ] 修改文章後重新 build,搜尋結果不再顯示舊內容。

Pagefind 會依照 <html lang> 分開建立不同語言的索引。中文不是以空白分隔,所以不要只測試英文;實際用幾個網站讀者會搜尋的中文詞組驗收,才知道結果是否符合預期。

常見問題排查

搜尋框出現,但沒有任何結果

先檢查 _site/pagefind/ 是否存在,以及正式網址載入 Pagefind 資產時是否 404。重新執行 Eleventy 和 Pagefind,並確認網站的 base URL 沒有讓 /pagefind/ 路徑指錯。

中文幾乎搜不到

檢查 <html lang> 是否缺少或寫錯。改成 zh-Hant 後,清除舊的 pagefind/ 資料夾,再重新建立索引。

首頁或分類頁沒有出現在結果裡

可能只有文章 layout 有 data-pagefind-body。在希望被搜尋的首頁或分類頁,也加上這個標記。

搜尋結果一直出現導覽列文字

在 header、footer 或其他固定元件加上 data-pagefind-ignore,再重新建立索引。

本機測試時程式失敗

不要用 file:// 開啟 HTML。使用 npx pagefind --site _site --serve,或其他能提供靜態檔案的本機伺服器。

結語:先用靜態索引解決真正的需求

對大多數 Eleventy 部落格來說,站內搜尋的第一步不需要資料庫或即時搜尋服務。只要:

  1. 在 layout 加入 Pagefind UI。
  2. 設定 lang="zh-Hant"data-pagefind-bodydata-pagefind-ignore
  3. 將 Pagefind 接到每次 build,並用中文關鍵字驗收。

就能讓讀者在瀏覽器裡搜尋已發布的文章。若未來真的需要會員權限、個人化結果或即時資料,再考慮升級到後端或託管搜尋服務。

下一步:先在測試環境跑一次 npx -y pagefind --site _site,確認 pagefind/ 產生並完成繁體中文搜尋驗收,再把同一組 build 流程放進正式部署。

推薦工具/資源

  • Pagefind:適合 Eleventy、文件站和靜態文章站,從 build 後的 HTML 建立瀏覽器端搜尋索引。
  • Eleventy:適合想保留靜態輸出、又不想為站內搜尋維護後端的小型網站。

參考來源