hugo에 검색 기능 추가하기 - pagefind

Page content

Why not Agollia

algolla 는 site indexing 을 위해 Algollia 서버로 정보를 보내는 듯 함. 대신 hugo에 아주 seamless 하게 연동이 되는데. 좀 아쉽네. (Privacy 건은 좀 더 확인해 봐야겠다)

Algollia를 잘 결합해서 사용하는 사이트 하나 https://inchan.dev Search를 클릭하면 입력 창의 크기가 자동으로 커져서 결과가 보여지는 창도 적당해서 보기 좋다.

Install Pagefind

설치는 npx를 이용해서 설치하거나, cargo build하거나. 혹은 github에 올려져 있는 바이너리 다운받아 설치하거나. 이 중에 마지막 방법 선택

https://github.com/CloudCannon/pagefind/releases

wget https://github.com/CloudCannon/pagefind/releases/download/v0.12.0/pagefind-v0.12.0-x86_64-unknown-linux-musl.tar.gz

이것 보다는 multi-byte 처리를 고려한 이 버전을 받는 게 좋을 듯함

wget https://github.com/CloudCannon/pagefind/releases/download/v0.12.0/pagefind_extended-v0.12.0-x86_64-unknown-linux-musl.tar.gz

How to run

./pagefind_extended --source "public"

Configuration File

  • pagefind.toml, pagefind.yml/yaml, pagefind.json 등을 사용할 수 있다고 함.
  • 다만 아래와 같이 기본 값을 그대로 사용하는 경우에는 별도로 설정 파일을 만들 필요 없음.
source: public
bundle_dir: _pagefind

이 정보들은 환경변수를 이용해 설정할 수도 있음

PAGEFIND_BUNDLE_DIR="_pagefind" PAGEFIND_SOURCE="public" ./pagefind_extended

여기서 _bundle_dir은 indexing된 결과를 저장할 output directory를 의미 ( Configuring the Pagefind CLI 참고 )

Build a index

256MB, 1 core를 할당한 LXC 기반의 container에서 github-action을 실행하고 있어, 그 머신에서 pagefind_extended를 이용해서 빌드하라고 시켰는데 오잉. 중간에 pagefind가 kill되었다고 나온다.

5m 6s

> Run pagefind_extended --source public

Running Pagefind v0.12.0 (Extended)
Running from: "/home/cychong/actions-runner/_work/blog/blog"
Source: "public"
Bundle Directory: "_pagefind"

[Walking source directory]
Found 5204 files matching **/*.{html}

[Parsing files]
/home/cychong/actions-runner/_work/_temp/09bfda6f-b57f-454f-90b5-27d8e95e6908.sh: line 1: 20632 Killed pagefind_extended --source public
Error: Process completed with exit code 137.

OOM(Out Of Memory) 로 process 가 종료되는 경우를 종종 봐서(고작 16GB를 가진 mini3에서 kubernetes를 실행하다 보니 종종 pod가 OOM으로 종료되는 것을 봐서) 혹시나 하고 action-runner LXC의 메모리를 256MB에서 1024MB로 늘린 후 돌려보니 정상적으로 돌아간다.

실제 동작 중 system monitor를 보니 1GB를 모두 사용하는 경우가 있는데, 대부분 pagefind가 동작하는 시간이 아닐까 싶다.

실행 결과는 이렇게 나오는데 마지막에 있는 것 같이 indexing에 37초 가량이 걸린다.

$ pagefind_extended --source public --verbose

Running Pagefind v0.12.0 (Extended)
Running in verbose mode
Running from: "/home/cychong/actions-runner/_work/blog/blog"
Source:       "public"
Bundle Directory:  "_pagefind"

[Walking source directory]
Found 5204 files matching **/*.{html}

[Parsing files]
Did not find a data-pagefind-body element on the site.
↳ Indexing all <body> elements on the site.

[Reading languages]
Discovered 1 language: en
  * en: 4613 pages

[Building search indexes]
Language en:
  Indexed 4613 pages
  Indexed 82547 words
  Indexed 0 filters
  Indexed 0 sorts

Total:
  Indexed 1 language
  Indexed 4613 pages
  Indexed 82547 words
  Indexed 0 filters
  Indexed 0 sorts

Finished in 36.867 seconds

이제 빌드는 잘 되니 검색 결과를 이용할 수 있게 html 파일을 수정하면 될 듯.

blog에 추가

지금 사용하고 있는 mainroad theme는 sidebar widget을 이용해서 search 기능을 제공하고 있다. config.toml 설정 중 일부

  widgets = ["search", "categories", "series", "taglist"]

이 search 기능은 google 기능을 이용하는데 현재 블로그가 internal network에서만 접근할 수 있게 되어 있다 보니 검색이 제대로 동작하지 않는다. 외부에서 접근이 가능해도 검색 기능이 그닥 쓸모있지 않았지만.

이제 할 것은 pagefind documentation 에 있는 search 내용을 처리할 코드를 layouts/partials/widgets/search.html에 만들기. 아래 코드는 pagefind documentation에 있는 내용과 기존에 사용하던 다른 widget의 코드를 합쳐서 기존 mainroad theme과 어울리게 만든 것이다.

<link href="/_pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/_pagefind/pagefind-ui.js" type="text/javascript"></script>

<div class="widget-categories widget">
	<h4 class="widget__title">Search</h4>
	<div id="search"></div>

	<script>
		window.addEventListener('DOMContentLoaded', (event) => {
			new PagefindUI({ element: "#search" });
		});
	</script>
</div>

검색을 하면 이렇게 검색 창 아래에 결과가 나온다.

github action 에 추가

자동으로 hugo로 빌드할 때마다 자동으로 indexing을 할 수 있게 github의 action flow 수정한다. 아래의 경우는 local github action runner를에서 미리 설치해 높은 pagefind_extended를 사용하는 경우이고, cat .github/workflows/main.yml

      - name: Build
        run: |
          rm -rf public/*
          hugo -t mainroad          

      - name: indexing with pagefind
        run: |
          pagefind_extended --source public          

      - name: Deploy
        run: |
          pwd
          rsync -az public/* cychong@${{ secrets.GH_BLOG_TARGET }}:/home/cychong/public/blog/          

github.com이 제공하는 runner를 사용하는 경우에는 이렇게 npx pagefind@latest로 명시했다. pagefind 썰치 문서에 보면 npx pagefind를 실행하면 자동으로 pagefind_extended를 설치한다고

Running Pagefind via npx will download the pagefind_extended release, which includes specialized support for indexing Chinese and Japanese pages.

      - name: Run Pagefind
        run: npm_config_yes=true npx pagefind@latest --source "public"

Reference