個人サイトをHugoに移管した話

みなさん、お久しぶりですtatsyです。この記事は、ブログのリハビリも兼ねた記事で、若干内容が薄めです。

気づくといろいろあった2020年ももう終わりで、今年は一度もブログを更新していないことに気付きました (といっても昨年もレイトレ合宿の報告だけでしたが…)。

というわけで、何か記事を書こうと思い立ち、今年何かとお世話になった静的ウェブサイト・ジェネレータについて書いてみようと思いました。ちなみに、私個人はPHPから始まり、Node.js, Jekyll, Hugo, Sphinxなどえサイトを作ってきましたが、そのような経験からの一意見としてお読みいただければ幸いです(本業が何かわからない…)。

結局Hugoの何がいいの?と言うことだけ知りたい人は、最後のまとめだけお読みください。

なぜ静的サイトジェネレータを使うのか?

私は、これまで、自分の個人ページも含め、いくつかのウェブサイトを作ってきましたが、学生の頃に作ったものの多くがPHPで書かれた動的なものであったのに対して、最近は一貫して静的なサイトを作っています。

そもそも動的サイトをあえて使っていたのは、私が学生時代にアルバイトでウェブページを作っていて、その時にPHPを使っていたことが大きく、惰性で個人サイトもPHPで作っていたというのが大きかったです。

ですが、よくよく考えてみると、個人ページには動的サイトの昨日はほとんど必要なく、それよりも更新の手間が少ないものの方が嬉しいということになり、メタ情報だけを用意して、サイト生成を自動化できる静的サイトジェネレータを使おうと思いました。

当初は、自分の個人ページも含めGulpというNode.jsベースのサイトジェネレータを使っていて、これはこれで良かったのですが、一つ懸案事項がありました。以前、Gulpを使っていた時は、前の言い方でJade、今の言い方で PugというHTMLの亜種のようなものを書いていたのですが、それでさえ面倒になり、 やはりMarkdownを使ってかける方が便利なのではないかと思ったことです。

HugoとJekyllの比較

そこで、候補となったのがHugoJekyllとです。ここで今更強調するひつようはありませんが、簡単な違いをまとめると以下のようになります。

HugoJekyll
言語GoRuby
スター数49k42k

Github上のスターの数でいうと、かなり拮抗していますが、最近はHugoが伸びている印象があります。やはり、Goで開発されているので、そのサイト生成スピードには有利な面があるように思います。

一方で、JekyllはGithub Pagesにデフォルトでサポートされていて、結構使い勝手は良く、実際、いくつか勉強用のページをJekyllで作ったりしました。特にJekyll+Kramdownの使い勝手は個人的にはすごく良くて、特にHTMLのフィールドをMarkdownのタグに足して[title](url){:target="_blank"}のようにかけるのはすごく便利でした。

ただ、上記の通り、以前からTravis CI経由でGithub Pagesにデプロイすることはやっていたので、自動でデプロイされるのはそこまで魅力的には映らず、またGithub Pagesの自動デプロイだと、サポートされているバージョンが少し低く、使える機能が制限されることもネックになりました。

あとは、単純にページ構築の速度が遅い。数ページのサイトなら耐えられるかもしれないけど、このブログのようにサイトの数が大きくなるとCtrl+Sを連打しようものなら、大変なことになります。だから、ページ構築の速度は大事だと思いました。

しかも、最近はGithub Actionsが現れたことで、とても簡単にHugoもデプロイできるようになり、しかもTravis CIではお金を払わないとできなかったプライベートレポジトリからのデプロイも可能になりました。敷居がグッと下がったことで、新しくページを作るときにも、ほぼテーマだけを選べば良くなったのは大きいです。

その上、Hugoにはshortcodesという仕組みがあって、短いコードスニペットのようなものを自分で作成することができます。HugoでデフォルトのMarkdownパーザはGoldmark (0.60よりまえはBlackfriday)ですが、Goldmarkでは上記のKramdownにあるフィールド機能をサポートしていません。

ですが、shortcode (名前を仮にexternal.mdとします) を layout/shortcodes/ ディレクトリに作成して

<a target="_blank">{{ .Get src }}</a>

のように書いておくと、実際のMarkdownの方では、

{{< external src="url" >}}

と書くことで、外部リンクを実現できるわけです。もちろん、属性をその場で変えることはできませんが、いざと慣ればHTMLをそのまま書くこともできるので、よく使う機能 (画像のポップアップとか)だけサポートしてくれれば十分でした。ちなみに、一応、見出しに対しては属性を追加する機能があるのですが、なぜかリンクに対してはこれは使えないようです(もし使えたら教えて欲しい)。

私がやったこと

私が個人サイトを刷新するにあたりやったことは以下の通りです。

  1. Gulp時代からのメタ情報 (JSONで書かれている)をパーズしてページに変更するためのHugoのテンプレートを作成
  2. ここのプロジェクトページを作成するためのテンプレートを作成
  3. その他、画像のポップアップなどの便利なshortcodesを用意
  4. デプロイのためのGitHub Actionをworkflowを用意

1については、HugoでもJSONファイルをメタデータとして読み込む機能があって、dataと言うディレクトリにJSONファイルを配置しておくだけです。あとは、それをHugoのテンプレートの中で読み込むだけです。

1, 2共通で、テンプレートの作成については、まず、Hugoのテーマを集めたページから自分の好きなものを探してきて themes フォルダに配置しました。その上で、テーマをエディットしていくのですが、Hugoはlayoutsフォルダにある同名のテンプレートを上書きするので、themes以下には基本となるテーマを用意しておいて、それを拡張したい場合には、サイトのルートに配置したlayoutsに同名のテンプレートファイルを作成することになります。

これはJekyllでも共通ですが、個別ページに必要なタイトルなどのメタ情報は、Markdownの先頭にヘッダ情報として、JSON, YAML, TOMLのいずれかの形式で書いておくことができるので、プロジェクトページに関しては、余計なものを書くことはせず、できる限り、このヘッダ情報だけで完全なページができるようにしました。

3のshortcodesの用意については、それほど凝ったことはしていなくて、画像を lightbox を使ってポップアップさせるものを用意した以外は、特には用意していません。あとはfont-awesomeの呼び出しとかを用意しておくと便利かなとは思います。

shortcodesによる拡張は、いろいろやっておくと便利になることは他にもあると思うのですが、あまり、shortcodesに依存しすぎると、違う環境に移行できなくなるので、現状は、CSSやJavaScriptを駆使して、特定のidやクラスを持つオブジェクトにだけ、特定の操作を行う、などのやり方を取っています。

4のworkflowの用意ですが、これに関してもほとんどやることはなくて、こちらのレポジトリにあるworkflowのコードをほぼコピペすれば完了です。

ちなみに、以前はGithub Pagesはgh-pagesというブランチにページ情報をプッシュすると勝手にページが作られたのですが、現在はGithubの「Setting」→「Options」→「Github Pages」で、どのブランチを使うかなどの設定をする必要があります。

Hugoの弱点

一応、Hugoのよくなかったところ、をまとめておくと、個人的には以下の点が気になりました。

  1. 推奨されるディレクトリの構成が分かりづらく、その割にルールに厳しい
  2. 情報が、ほぼ公式のドキュメントしかなく、ドキュメントもあまり親切でない

つまり一言で言ってしまうと、便利だけど、どう使うかを理解するのが大変ということです。特に1番についてですが、Hugoはフォルダ構成がある程度厳格に決まっていて、例えばdataフォルダにはデータを入れる、ページの情報はcontentに入れる、ページのテンプレートはarchetypesに入れるなどの決まりがあります。

これらの違いを理解するのが最初苦労したところで、その割に、あまり親切に解説したページがなく…私の読解能力の無さかもしれません。ですが、人口は増えてきているので、少なくとも英語の範囲ではあまり問題にならない気もします。あとはGitHubのissueをよく見るとか…。

まとめ

Hugoの一番の利点は、やはりサイト構築の速さだと思います。このブログもWordPressから移行しましたが、ページ数が100以上あっても、1秒程度でサイト構築が可能な点は嬉しいです。