静的ブログサイトを Zola で作る

Rust 製 SSG ツール Zola で作ったウェブページを GitHub Actions を使って GitHub Pages にホストする

hata published on
11 min, 2046 words

Categories: web

Zola🔗

Zola は SSG - Static Site Generator (静的サイト生成)のツールです。 Rust で書かれていることによる高速なビルドと豊富な機能が特徴です。

似たツールとしては Golang 製の Hugo があります。 Hugo のほうが歴史も長く枯れており知名度と人気があるため Theme (デザインのテンプレート)が豊富に公開されています。 また、ビルド速度は Zola より Hugo のほうが速いようです。 とはいえ Zola もその他の言語の SSG に比べると十分に速いです。 ざっくり体感として、数百ページを超えるとビルドのラグを少し感じなくもないです。 数千ページを超えると数秒以上かかりました。 Hugo だとその程度の量は秒未満で処理できることが多いです。 本当にページが莫大に増える見込みがあるようであれば、事前にページを大量生成してビルド時間を疑似体験・簡易比較しておいてもいいかもしれない(けど、個人的には気にするほどではないと思う)。

Hugo にない Zola の特徴的な機能としては 検索機能 があります。 ビルド時に検索のインデックスを静的に生成し、JS から使うことができるようにすることが可能です。 ただし、私が試した限りでは日本語でインデックスを作ることができませんでした。 GitHub の README に Hugo との機能比較がより詳細に記述されています。

Install Zola🔗

# Mac
brew install zola

# Windows
scoop install zola
# or
choco install zola
zola -V
# => zola 0.14.1

Init Zola🔗

zola init <your_project_name>
cd ./<your_project_name>
zola serve

http://127.0.0.1:1111 がタイムアウトせずに反応が返ってくればこの時点では OK 。 以下のようなディレクトリ構成になっているはず。

$ tree -L 1
.
├── config.toml   # Zola の設定ファイル。TOML フォーマット。
├── content       # ブログ記事などのコンテンツのファイルをおさめる。 .md など。
├── sass          # SASS をおさめる。 SASS 以外は無視される。 sass/foo/bar.sass -> public/foo.bar.css と変換される。
├── static        # 画像や JS などの静的なファイルおさめる。
├── templates     # テンプレートのファイルをおさめる。 Rust の Tera フォーマット。
└── themes        # Theme という、有志が公開してくれているデザインテンプレートをおさめる。 git submodule でいれる。

5 directories, 1 files

theme を適用する。 今回は RatanShreshtha/DeepThought を使わせてもらいました。 RatanShreshtha さん、ありがとうございます。

git init
git submodule add https://github.com/RatanShreshtha/DeepThought.git themes/deep-thought

設定オプションは

  • Zola 共通のは https://www.getzola.org/documentation/getting-started/configuration/
  • この Theme 特有のは https://github.com/RatanShreshtha/DeepThought#theme-options

あたりに全部乗ってるのでまるまるコピーすれば OK 。config.toml[extra] 以下が Theme 特有の設定オプションの箇所。

base_url = "https://<github_id_or_organization_name>.github.io/<repository_name>"
title = "Hoge Blog"
description = "ほげブログ"
default_language = "en"
theme = "deep-thought"
output_dir = "public"
compile_sass = true
minify_html = true
taxonomies = [
    { name = "categories", feed = true, paginate_by = 10 },
    { name = "tags", fees = true, paginate_by = 10 },
]
build_search_index = true

[markdown]
highlight_code = true
highlight_theme = "zenburn"

# When set to "true", emoji aliases translated to their corresponding
# Unicode emoji equivalent in the rendered Markdown files. (e.g.: :smile: => 😄)
render_emoji = true

external_links_target_blank = true
external_links_no_follow = true
external_links_no_referrer = true

[link_checker]
# Skip link checking for external URLs that start with these prefixes
skip_prefixes = []

# Skip anchor checking for external URLs that start with these prefixes
skip_anchor_prefixes = []

[extra]
 { code = "en", nav_items = [
  { url = "$BASE_URL/", name = "Home" },
  { url = "$BASE_URL/posts", name = "Posts" },
  { url = "$BASE_URL/docs", name = "Docs" },
  { url = "$BASE_URL/tags", name = "Tags" },
  { url = "$BASE_URL/categories", name = "Categories" },
 ]},
]

# Author details
[extra.author]
name = "<your_name>"

[extra] を除く部分では base_url のみが必須指定要素で、他はなくても OK 。

{ url = "$BASE_URL/posts", name = "Posts" }, という設定があるが、ここがこの Theme におけるサイトのヘッダの記事一覧に対応している。 これにあわせて、記事を作成してみる。

  • touch contetnt/posts/2021-11-13-hello-zola.md
+++
title = "Hello, World"
description = "こんにちは、世界"
draft = false
[taxonomies]
tags = ["hoge", "fuga"]
categories = ["foo"]
[extra]
toc = true
+++

## 記事本文はここにマークダウンで記述していく・・・

###  111
あああ

###  222
いいい

###  333
ううう

Front Matter で指定できる内容の一覧は https://www.getzola.org/documentation/content/page/#front-matter を参照。

  • touch contetnt/posts/_index_.md

これは、/posts URL にアクセスしたときに記事の一覧を出すのに作っておかなければならない。 Front Matter description のディスクリプションは記事一覧ページで表示される。 このあたり Hugo とは役割が違う。

+++
description = "記事の一覧です。"
+++

ローカルで確認🔗

zola serve --drafts

で起動。 --drafts オプションは Front Matter で draft = true となっている記事も含めてビルドするという指定。 通常、本番ビルド時には付けない。 http://127.0.0.1:1111 を開いてページが表示され、ヘッダから記事をたどって見ることができていれば OK 。

zola serve している間は public というフォルダができていることに気付く。 Zola ではビルドした成果物はデフォルトではそこに出力されるので、Git 管理から除外しておく。

echo "/public/" > .gitignore

次に GitHub Actions のビルド用ワークフローを作成

  • touch .github/workflows/build-and-deploy-gh-pages.yml
on:
  workflow_dispatch:
  push:
    branches:
      - main
  pull_request:
name: Build and deploy GH Pages
jobs:
  build:
    runs-on: ubuntu-latest
    if: github.ref != 'refs/heads/main'
    steps:
      - name: checkout
        uses: actions/checkout@v2
      - name: build only
        uses: shalzz/zola-deploy-action@v0.14.1
        env:
          TOKEN: ${{ secrets.PAT }}
          BUILD_DIR: .
          BUILD_ONLY: true
  build-and-deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: checkout
        uses: actions/checkout@v2
      - name: build and deploy
        uses: shalzz/zola-deploy-action@v0.14.1
        env:
          TOKEN: ${{ secrets.PAT }}
          BUILD_DIR: .
          PAGES_BRANCH: gh-pages

詳細は https://github.com/shalzz/zola-deploy-action#usage を参照。

さて、上記ワークフローはビルド成果物を gh-pages ブランチにコミットとプッシュする挙動になっている。 その権限を Actions に与えるために GitHub の Personal Access Token を払い出して、このリポジトリの GitHub Secrets に登録しておく。 Token の Scope は repo とかでいい。 上記の例であれば PAT という名前で Secrets に登録している。

最後に忘れずに

touch .nojekyll

しておく。GitHub Pages はもともと Jekyll 専用だったので、これをしないと Jekyll 以外の SSG をホスティングできない仕様になっている。

プッシュ & ビルド & デプロイ🔗

GitHub に Push する。 https://github.com/<your_github_id>//actions でワークフローの進捗が見えているはず。 成功すれば、 gh-pages ブランチが作成され、ビルド成果物一式がそこに入っているはず。

https://github.com/<your_github_id>//settings/pages 見ると、設定も自動で作られて、ホスティングされた URL が見れるはず。 ページを開いて確認。 ついでにヘッダの 🔍 ボタンから検索を試してみて。ASCII 文字だけでよろしく。

注意点・はまりどころ🔗

zola serve がちょっとしたファイル変更でよく落ちる。再起動(再実行)すればいいだけだが、かなり面倒。

categoriestags の配列の要素に空文字 ( "" ) があるとバグるので、気を付ける。

hugo のように新規記事作成サブコマンドやそのときに使えるひな形のような機能がない。僕はこんな感じのコマンドを Makefile に置いている。

cp dev/posts/template.md content/posts/`date "+%Y-%m-%d-"`generated-new-post.md

まとめ🔗

SSG はほとんどのユースケースでは、 Hugo を選択するのが無難ではないだろうか。 Hugo は機能も Theme も豊富で、枯れていて、なによりボリュームが大きくなっても ビルドが爆速

しかし、 Zola も実用上はそこまで遜色ない。検索機能など欲しい機能が Zola にしかないなら選択肢になると思う(ただ、日本語が、、)。

書くのが疲れてきたので、Google Domain の設定は別エントリに後日まとめる。

(追記) 続き を書いた。