ブログをZolaに移行した
ブログをZolaに移行した。
今まではHugo
とか、Docusaurus
とか使ってみたものの、なんかいまいちで…。
何が気に入らなかったかというと、機能性と速度。
機能でいうと、検索ができなかったり、Disqusに対応していなかったり…。
テーマによっては対応しているものもあるんだけど、今度はビルドが遅くてプレビューがめんどくさくなってしまったり。
以前からRust製のZolaが気になってチェックしていたものの、テーマが少なくて移行する気にはなれなかった。
最近になって、「いいテーマないかなぁ〜」とテーマを眺めていたらよさそうなテーマを発見!
DeepThought
https://www.getzola.org/themes/deepthought/
ローカルで確認してみたところ、結構しっくり来たのでブログの移行を検討して、今に至る。
Zolaをインストール
まずはzola
をインストール。
brew install zola
あとで発覚するんだけど、brew
でインストールしたzola
は検索が使えない(小文字zola
はコマンドを指す)。
記事を投入
今まで書いていた記事 (Markdown) をcontent
フォルダにコピー。
_index.md
も作成する。
テーマをカスタマイズ
トップページをブログ一覧に変更
このテーマ、トップページがHome
になっているので、トップページにブログ記事の一覧を表示するようにカスタマイズする。
テンプレートにあるsection.html
をindex.html
として使うことで、ブログ記事の一覧表示を実現する。
cp ./themes/DeepThought/templates/section.html ./templates/index.html
あとはzola serve
で動作確認。
実際に確認してみるといろいろと気になることが…。
read more
が動作してない- パスが今までと異なる
カテゴリ
とタグ
が機能していない
read more
read moreは<!-- more -->
のようにmore
の前後に空白が必要。
URLのパス修正
他のSSG
では、frontmatter
にslug
を定義してURLとしていると思うが、Zola
はディレクトリ構成がそのままURLになるらしく、_index.md
を各所に作らなければならないようだったので、content
ディレクトリにすべて保存している(うまいこと_index.md
を継承する方法があるのかもしれないが、知らない)。
この方法を採ると、今までとURLが変わってしまうので困る。
そこで、URLはfrontmatter
のpath
で指定する。
この記事の場合はこんな指定。
path = "2022/06/03/moved-blog-to-zola"
パスの先頭に/
は書いてはいけない。
参考ページ
https://www.getzola.org/documentation/content/page/
カテゴリとタグの書き方
Zolaはカテゴリとタグの書き方が他のSSGと違った。
[taxonomies]
categories = ["blog"]
tags = ["blog", "Zola"]
frontmatterがYAML
の場合、hugo convert
を使うと一気にTOML
に変換できる。
https://gohugo.io/commands/hugo_convert_totoml/
複数行を置換する場合、Visual Studio Code
かBBEdit
あたりが使いやすい。
参考ページ
https://zenn.dev/anz/scraps/ebf857a5cbcfb6
日本語検索
Zolaは検索に対応しているんだけど、標準では日本語検索に対応していないので、日本語検索に対応させるのは少々面倒。
zola
は日本語の辞書を持っていない- 日本語辞書を含む
zola
を作らなくてはならない
- 日本語辞書を含む
zola build
で作れるインデックスはdefault_language
の1種類のみ- 日本語検索はできるけど、英単語検索はできない…という状況に陥る
- 読み込めるインデックスは1ファイルのみ
- 日本語インデックスと英単語インデックスを作ってもそのままでは両方読み込まない
これらを解決しないと普通に検索できないということ。
上記の解決策を下に書いていく。
日本語辞書を持つZolaを作成
日本語検索に対応する方法はオフィシャルサイトに書いてある。
Note: By default, Chinese and Japanese search indexing is not included. You can include the support by building zola using cargo build --features search/indexing-ja --features search/indexing-zh. Please also note that, enabling Chinese indexing will increase the binary size by approximately 5 MB while enabling Japanese indexing will increase the binary size by approximately 70 MB due to the incredibly large dictionaries.
https://www.getzola.org/documentation/content/multilingual/
日本語検索に対応するzola
を作成するコマンドは次のとおり。
cargo build --features search/indexing-ja --release
ビルド自体はたいしたことなくて、上記コマンドで解決する。
ただし、Rustのビルドは遅いと言われているように、Zolaのビルドも遅い!
一回ビルドするだけならいいんだけど、記事を公開する度に毎回ビルドする場合はきつい。
日本語検索に対応したときのzola
自体のファイルサイズはこちらの記事をどうぞ。
https://www.jpgov.art/posts/zola-binary-columes-with-ja-zh-support/
検索時に必要なファイルをダウンロード
不足しているのは下の3ファイル。
これらをダウンロードしてstatic
に保存。
一部、修正が必要なところがある。
diff --git a/static/lunr.jp.js b/static/lunr.jp.js
@@ -96,7 +95,10 @@
}
})();
- lunr.Pipeline.registerFunction(lunr.jp.stemmer, 'stemmer-jp');
+ lunr.Pipeline.registerFunction(lunr.jp.stemmer, 'stemmer-ja');
+ lunr.jp['wordCharacters'] = '一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9';
+ lunr.jp.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.jp.wordCharacters);
+ lunr.Pipeline.registerFunction(lunr.jp.trimmer, 'trimmer-ja');
stemmer-jp
はjp
とja
の違いがある(pとaが違う)ので要注意。
英語と日本語の検索結果をマージ
テーマの検索ロジックを、日本語と英語の複数インデックスに対応させる。
テーマで使っているsite.js
を持ってきて編集する。
cp ./themes/DeepThought/static/js/site.js ./static/js
日本語インデックス (searchIndex
) の他に、英単語インデックス (searchIndexEn
) も読み込んでおく。
両者の結果をマージして検索結果とする仕組み。
searchIndex
とsearchIndexEn
はzola build
で作成するので、後述。
diff --git a/static/js/site.js b/static/js/site.js
@@ -139,12 +139,13 @@ function search() {
};
var currentTerm = "";
var index = elasticlunr.Index.load(window.searchIndex);
+ var indexEn = elasticlunr.Index.load(window.searchIndexEn);
$searchInput.addEventListener(
"keyup",
debounce(function () {
var term = $searchInput.value.trim();
- if (term === currentTerm || !index) {
+ if (term === currentTerm || !index || !indexEn) {
return;
}
$searchResults.style.display = term === "" ? "none" : "block";
@@ -153,7 +154,9 @@ function search() {
return;
}
- var results = index.search(term, options);
+ var resultsJa = index.search(term, options);
+ var resultsEn = indexEn.search(term, options);
+ var results = resultsJa.concat(resultsEn);
if (results.length === 0) {
$searchResults.style.display = "none";
return;
参考サイト
https://qiita.com/dalance/items/0a435d66e29f505faf6b
ビルド
ビルドする際の注意点がある。
zola
は日本語インデックス対応版を使う- ビルド時に英語インデックスと日本語インデックスの2つを作る
2つのインデックスを作成
英語と日本語のインデックスを作る方法は単純で、ビルドを2回する。
default_language
はja
をベースにしたいので、初めに英語インデックスだけ作る都合上、config.toml
のdefault_language
をen
にしておく。
それと、日本語インデックスの作成に結構時間がかかるので、ローカルではen
のままzola serve
で確認した方が効率がいいという理由もある。
# default_language = "en" で 英語インデックス作成
zola build
cp ./public/search_index.en.js .
# default_language = "ja" で 日本語インデックス作成
sed -i -e 's/^default_language = "en"/default_language = "ja"/' config.toml
./zola build
# 英語インデックスの変数名を変更し、publicにコピー
sed -i -e 's/^window.searchIndex =/window.searchIndexEn =/' ./search_index.en.js
cp ./search_index.en.js ./public
これで、下表の状態になる。
インデックス | ファイル名 | 変数名 |
---|---|---|
英語 | search_index.en.js | searchIndexEn |
日本語 | search_index.ja.js | searchIndex |
この表の内容はsite.js
で参照しているので、先述のsite.js
を参照。
ここまでで検索は解決。
公開
今回はCloudflare Pages
を使ってみることにした。
GitHub のposts
ブランチに push で GitHub Actions を使って build & publish をする。
ここで困ったのは 日本語インデックス対応版zola
のビルド時間。
初めはキャッシュで解決しようと actions/checkout@v3 を使ってみたんだけど、Zolaをsubmodule
にしていたせいでキャッシュが効かず。
次に日本語インデックス対応版zola
をartifact
として保存しておき、それを活用しようと考え、 download-artifact を使ってみたんだけど、ビルドしたzola
をうまくダウンロードできず。
最終的にはdownload-workflow-artifactで解決した。
Zolaをコンパイルすると公開までの時間は16分
くらいかかる。
artifactに置いといたzola
を使うと3分
くらいで済む。
Cloudflare Pagesのプレビュー機能
Cloudflare Pages
はmain
ブランチ以外だとプレビューとして扱い、サブドメインで専用ページを用意してくれる。
公開する場合はmain
ブランチを使うことになるということ。
今回はcloudflare/wrangler-action@2.0.0を使った。
コメント
ある程度動くようになったものの、デプロイしてみるとコメントが表示されないことに気付いた。
コメントはDisqusを使ったんだけど、うまく動作しなかったようだ。
Disqusにログインして状況を確認してみると、なぜかトップページのURLでレコードが作成されていた。
明らかに実装側の問題だろう…ということで、ソースをコピーして、少々修正。
cp ./themes/DeepThought/templates/page.html ./templates
diff --git a/templates/page.html b/templates/page.html
--- a/templates/page.html
+++ b/templates/page.html
@@ -184,8 +184,8 @@
{% if page.extra.comments and config.extra.commenting.disqus %}
<script>
var disqus_config = function () {
- this.page.url = "{{config.base_url | safe}}";
- this.page.identifier = "{{ current_path | safe}}";
+ this.page.url = "{{current_url | safe}}";
+ this.page.identifier = "{{current_url | safe}}";
};
(function () {
各ページ (Markdown) のfrontmatter
にコメントを有効にする記述が必要。
[extra]
comments = true
これでコメントも今まで通りになった。
課題
カテゴリとタグのURLがおかしい。
たとえば、こんな感じ。
名称 | URLのパス |
---|---|
ブログ | burogu |
本 | ben |
これを解決するにはfrontmatter
にこのように書けばいいらしい。
tags = [{name = "ブログ", slug = "blog"}, {name = "本", slug = "book"}]
でも、これをやるのは面倒なのでしばらく放置。
参考ページ
https://zenn.dev/anz/scraps/ebf857a5cbcfb6
まとめ
ディレクトリ構成
blog
├── config.toml
├── content
│ ├── ︙
│ ├── 2022-06-03T2248-ブログをZolaに移行した.md
│ └── _index.md
├── static
│ ├── js
│ │ └── site.js
│ ├── lunr.jp.js
│ ├── lunr.stemmer.support.js
│ └── tinyseg.js
├── templates
│ ├── base.html
│ ├── index.html
│ └── page.html
└── themes
└── DeepThought
config.tomlの主要部分
base_url = "https://blog.teapla.net"
build_search_index = true
default_language = "en"
theme = "DeepThought"
taxonomies = [
{name = "categories", feed = true, lang = "ja"},
{name = "categories", feed = true, lang = "en"},
{name = "tags", feed = true, lang = "ja"},
{name = "tags", feed = true, lang = "en"},
]
navbar_items = [
{ code = "ja", nav_items = [
{ url = "$BASE_URL/", name = "Blog" },
{ url = "$BASE_URL/tags", name = "Tags" },
{ url = "$BASE_URL/categories", name = "Categories" },
]},
{ code = "en", nav_items = [
{ url = "$BASE_URL/", name = "Blog" },
{ url = "$BASE_URL/tags", name = "Tags" },
{ url = "$BASE_URL/categories", name = "Categories" },
]},
]
[extra.commenting]
disqus = "${DISQUS_SHORTNAME}"
GitHub Actionsのワークフロー
Zolaをビルドしてartifact
に置くワークフロー
name: Upload release zola
on:
workflow_dispatch:
env:
ZOLA_TAG: v0.15.3
jobs:
build:
name: Upload Zola binary
runs-on: ubuntu-latest
steps:
- name: Build Zola
run: |
git clone https://github.com/getzola/zola.git -b ${{ env.ZOLA_TAG }} --depth 1
cd zola
cargo build --release --features search/indexing-ja
- name: Create Release
uses: actions/upload-artifact@v2
with:
name: zola-${{ env.ZOLA_TAG }}
path: ./zola/target/release/zola
記事をpushしたときに動くワークフロー
途中でしていている${RUN_ID}
は、日本語インデックス対応zola
を作成したワークフロー実行時のID。
artifactのURLから${RUN_ID}
を控えておく必要があるし、zola
のバージョンを上げたら${RUN_ID}
を変える必要がある。
name: Publish to Cloudflare Pages
'on':
workflow_dispatch:
push:
branches:
- main
env:
ZOLA_TAG: v0.15.3
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout theme
run: |
mkdir -p themes/DeepThought
cd themes/DeepThought
git init
git remote add origin https://github.com/RatanShreshtha/DeepThought.git
git fetch --depth 1 origin 8bf64262791f968dcc3e72d82195f9ebb1a39a69
git checkout FETCH_HEAD
rm -fr ./content
rm -fr ./static
- name: Download zola-${{ env.ZOLA_TAG }}
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{ secrets.UPLOAD_PAT }}
workflow: upload-zola.yml
workflow_conclusion: success
run_id: ${RUN_ID}
name: zola-${{ env.ZOLA_TAG }}
- name: Make search_index.en.js
run: |
chmod u+x ./zola
./zola build
cp ./public/search_index.en.js .
- name: Build pages
run: |
sed -i -e 's/^default_language = "en"/default_language = "ja"/' config.toml
./zola build
sed -i -e 's/^window.searchIndex =/window.searchIndexEn =/' ./search_index.en.js
cp ./search_index.en.js ./public
- name: Publish
uses: cloudflare/wrangler-action@2.0.0
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages publish public --project-name=${{ secrets.CLOUDFLARE_PAGES_PROJECT_NAME }}