Hugo で擬似的な無限スクロールを実装する

heroImage

1. はじめに

Hugo は,ページネーションがテンプレートとして標準搭載されています。しかし,無限ページングのテンプレートは標準搭載されていないため,フルスクラッチで実装する必要があります。実装するに当たって (1) JavaScript を用いて実装する方法と (2) Hugo の機能で実装する方法が考えられます。(1) と (2) は,共にソースコードが公開されているので,公開されているソースコードを活用します。また,本記事内で行っている作業は,以下の環境下で実行したものです。

2. ソースコード

公開されているソースコードに手を加えたものを以下に示します。一般的な無限ページングは,JavaScript を用いて DOM を操作することで実現しています。しかし,公開されているソースコードは Hugo に標準搭載されているページネーションの機能を応用して擬似的な無限ページングを実現しています。

1
{{ $paginator := .Paginate .Pages }}
2
{{ $pageSize := $paginator.PageSize }}
3
{{ $totalPostsToShow := mul $paginator.PageNumber $pageSize }}
4
{{ range $index, $el := (first $totalPostsToShow .Pages) }}
5
<div {{ if eq $index (sub $totalPostsToShow $pageSize) }} id="bottom" {{ end }}>
6
<a href="{{ .Permalink }}">{{ .Title }}</a>
7
</div>
8
{{ end }}
9
{{ if and (gt $paginator.TotalPages 1) ($paginator.HasNext) }}
10
<a class="nextpage" href="{{ $paginator.Next.URL }}#bottom">More</a>
11
{{ end }}

3. 実行環境構築

hugoBasicExample をベースに,実行環境を構築します。まずは,GitHub のリポジトリから hugoBasicExample を任意のディレクトリにクローンし,./hugoBasicExample/layouts/_default ディレクトリ直下に section.html を作成します。

Terminal window
1
$ pwd
2
$ /home/admin
3
$ git clone https://github.com/gohugoio/hugoBasicExample.git
4
$ cd hugoBasicExample
5
$ mkdir ./layouts/_default/
6
$ touch ./layouts/_default/section.html
7
$ tree
8
.
9
├── LICENSE
10
├── README.md
11
├── config.toml
12
├── configTaxo.toml
13
├── content
14
│   ├── _index.md
15
│   ├── about.md
16
│   ├── archives.md
17
│   ├── homepage
18
│   │   ├── about.md
19
│   │   ├── index.md
20
│   │   └── work.md
21
│   └── post
22
│   ├── _index.md
23
│   ├── emoji-support.md
24
│   ├── markdown-syntax.md
25
│   ├── math-typesetting.md
26
│   ├── placeholder-text.md
27
│   └── rich-content.md
28
├── layouts
29
│   └── _default
30
│   └── section.html
31
└── static
32
33
10 directories, 18 files

上記で作成した section.html を以下のソースコードに書き換えます。

1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8" />
5
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
<title>Document</title>
7
</head>
8
9
<body>
10
{{ $paginator := .Paginate .Pages }} {{ $pageSize := $paginator.PageSize }} {{ $totalPostsToShow := mul
11
$paginator.PageNumber $pageSize }} {{ range $index, $el := (first $totalPostsToShow .Pages) }}
12
<div {{ if eq $index (sub $totalPostsToShow $pageSize) }} id="bottom" {{ end }}>
13
<a href="{{ .Permalink }}">{{ .Title }}</a>
14
</div>
15
{{ end }} {{ if and (gt $paginator.TotalPages 1) ($paginator.HasNext) }}
16
<a class="nextpage" href="{{ $paginator.Next.URL }}#bottom">More</a>
17
{{ end }}
18
</body>
19
</html>

4. 動作確認

hugoBasicExample ディレクトリ直下に移動し,hugo server を実行します。正常に実行されると,http://localhost:1313/ に Web サーバーが立ち上がります。しかし,http://localhost:1313/ にアクセスしても index.html を設置していないため,ブラウザ上には何も表示されません。section.html の内容を表示させるために,http://localhost:1313/post/ にアクセスします。

Terminal window
1
$ pwd
2
$ /home/admin/hugoBasicExample
3
$ hugo server
4
5
| EN
6
-------------------+-----
7
Pages | 19
8
Paginator pages | 1
9
Non-page files | 0
10
Static files | 1
11
Processed images | 0
12
Aliases | 10
13
Sitemaps | 1
14
Cleaned | 0
15
16
Built in 13 ms
17
Watching for changes in /home/admin/hugoBasicExample/{content,layouts,static}
18
Watching for config changes in /home/admin/hugoBasicExample/config.toml
19
Environment: "development"
20
Serving pages from memory
21
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
22
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
23
Press Ctrl+C to stop

ブラウザで http://localhost:1313/post/ にアクセスすると,ブラウザ上に 3 つの記事タイトルと More ボタンが表示されます。表示されている More ボタンをクリックすることで,新たに 2 つの記事タイトルが表示されれば正常に動作しています。

5. おわりに

ここまで,Hugo に標準搭載されている機能を用いて擬似的な無限スクロールを実装する手順について記述してきました。擬似的な無限スクロールですが,完全な無限ページングと比較しても機能的な差はなく,ストレスを感じるようなこともありませんでした。また,config.tomlpaginate に設定されている数値を変更することで,表示される記事数を変更することが出来ます。