Hugoを0.118から0.167へ上げて分かった落とし穴

古いHugoを最新へ上げると、ビルドは通るのに一覧の件数、タグの見出し、コードの色が警告なしに変わる。0.118.2から0.167.0へ上げたときに止まったもの・変わったものと、旧版と新版を並べて見比べた進め方を解説する。

Hugoを0.118から0.167へ上げて分かった落とし穴

本記事はプロモーションを含みます。

はじめに:ビルドは通るのに、上げた後のサイトが前と違う

版を上げた後のビルドはエラーも警告も無く通るが、旧版と並べると一覧の件数・タグの見出し・コードの色が変わっている

2023 年の版のままだった Hugo のブログを、Hugo 0.118.2 から 0.167.0 へ、テーマ (PaperMod) を 2023-08 の版から最新へ上げた。消えた関数はビルドエラーで止まるので気付ける。困るのは、ビルドが通ったまま出力だけが変わるものだ。

結論から書くと、気を付けるのは次の 2 種類だ。

  • ビルドが止まるもの: resources.ToCSS と .Site.Social。止まるので、直す先を調べればよい
  • 警告なしに変わるもの: トップレベルの paginate が読まれない、一覧タイトルの頭文字が大文字になる、大小違いのタグの見出しがビルドごとに変わる、テーマの設定が効かなくなる

後者はビルドの成否では見つからない。旧版と新版の出力を並べて見比べ、何回かビルドして差分を取ると見つかる。この記事では、実際に踏んだものと、どう進めて何を選んだかを順に書く。

進め方:コピーで上げて、旧版と新版を並べる

リポジトリのコピーで上げ、ビルドエラーを直し、旧版と新版をブラウザで並べ、複数回ビルドして差分を取る

本物のリポジトリでいきなり版を上げると、壊れたときに元の出力と比べられない。そこで、リポジトリのコピーで上げて試した。

  1. コピーで Hugo とテーマを上げる
  2. ビルドエラーを 1 つずつ直す
  3. 旧版と新版を並べてブラウザで見比べる
  4. 何回かビルドして、出力の差分を取る

3 の見比べで、ダークモードの目次の背景、コードブロックのファイル名ラベル、スマホ幅の字下げのずれが見つかった。どれもビルドは通っていたので、画面を見なければ気付かなかった。

手元でテーマのテンプレートを上書きしているなら、それも最新のテーマに合わせて移し直す必要がある。筆者は single / archives / cover / post_meta / opengraph / twitter_cards の上書きを最新のテーマに移植し、不要になった head.html の上書きは消した。古いテーマからコピーした上書きは、消えた API を使っていることがある (次の節)。

直し方が一意なものは聞かずに直す

止まったもの・変わったもののうち、直し方が 1 つに決まるもの 7 件は、その場で直した (resources.ToCSS => css.Sass、paginate => pagination.pagerSize など)。

あわせて、Hugo の版を書く場所を .tool-versions だけにし、同じ値を持っていた .env を消した。版を 2 か所に書くと、片方だけ上げて手元と CI で別の版が動く。

ビルドが止まるもの:消えた関数とメソッド

resources.ToCSS は css.Sass に置き換え、.Site.Social は手元の上書きテンプレートが使っていた

0.118 前後から 0.16x へ上げると、次の 2 つでビルドが止まった (0.163 と 0.167 の両方で同じ結果)。長く非推奨だった API が消えたためだ。

  • resources.ToCSS: Sass を CSS にする関数。css.Sass に置き換える
  • .Site.Social: サイトの SNS 設定を引くメソッド
{{ $css := resources.Get "x.scss" | css.Sass }}  {{/* 旧: resources.ToCSS */}}

.Site.Social は、Hugo の内蔵テンプレートではなく、古いテーマから手元にコピーした上書きテンプレートが使っていた。エラーの出たファイルが自分の layouts/ にあるなら、上書きを最新のテーマの版で作り直す。

css.Sass のドキュメントには、組み込みの LibSass は v0.153.0 で非推奨になり、Dart Sass への切り替えを勧めるとある (css.Sass)。今回は止まった箇所を置き換えるところまでにした。

警告なしに変わるもの

ここからが本題だ。どれもビルドは成功し、エラーも警告も出ない。

paginate が読まれず、一覧が 10 件になる

トップレベルの paginate: 5 は読まれず一覧が 10 件になり、pagination.pagerSize: 5 に書き換えると 5 件に戻る

設定ファイルのトップレベルに書いた paginate は、新しい版では読まれない。一覧は既定の 1 ページ 10 件になる。設定キーなので、知らないキーとして捨てられ、何も表示されない。

pagination:
  pagerSize: 5   # 旧: paginate: 5

pagination の既定値は pagerSize: 10 (Configure pagination)。ページャの件数を数えないと気付かない。

一覧のタイトルの頭文字が大文字になる

タグ一覧の見出しが golang は Golang、GCP は Gcp になり、capitalizeListTitles: false で書いたとおりの綴りに戻る

上げた後、タグのページの見出しが golang から Golang に、GCP から Gcp に変わった。原因は capitalizeListTitles で、section・taxonomy・term の自動で付く一覧タイトルの頭文字を大文字にする。既定は true だ (All settings)。

capitalizeListTitles: false

これで書いたとおりの綴りに戻る。「Tags」のような一覧そのものの見出しは、content/tags/_index.md の title: で付ける。大文字の略語は Gcp のように崩れるので、技術ブログでは切っておく方がよい。

同じ版上げでは、Google Analytics も確かめておく。Hugo の内蔵テンプレートの privacy.googleAnalytics.respectDoNotTrack は既定が true で (Configure privacy)、ブラウザで Do Not Track を有効にした訪問は計測されない。上げた後に計測数が減ることがある。

大小違いのタグの見出しがビルドごとに変わる

AWS と aws のタグは 1 つにまとまり見出しの綴りがビルドごとに変わるが、content/tags/aws/_index.md に title を書くと固定される

記事ごとにタグの大小が揺れていると (ある記事は AWS、別の記事は aws)、Hugo は 1 つの term にまとめる。0.167 では、どちらの綴りが見出しに出るかがビルドのたびに変わった。0.118.2 では 3 回ビルドしても同じだった。筆者のブログでは 14 組がこれに当たった。

並列処理で、最初に処理されたページの綴りが採られているとみている (推測)。直し方は、term ごとに綴りを固定することだ。

# content/tags/aws/_index.md
---
title: AWS
---

対策の後に 3 回ビルドし、190 タグすべての見出しが旧版と一致することを確かめた。1 回のビルドの見比べでは気付かないので、複数回ビルドして見出しの集合を diff する。

テーマの設定が効かなくなり、コードの一部だけ色が付く

テーマと同じパスの空の chroma-styles.css をプロジェクトの assets/ に置くと、そちらが使われて chroma の配色ルールが消える

コードの色付けを highlight.js で行っていると、上げた後に highlight.js が知らない言語のブロックにだけ Hugo 側 (chroma) の色が付いた。最新の PaperMod は assets/css/includes/chroma-styles.css を常に読み込み、params.assets.disableHLJS を見なくなっていた。効かなくなった設定も、警告なしに無視される。

Hugo は、プロジェクトの assets/ にテーマと同じパスのファイルがあれば、そちらを使う。空ファイルを置けば、テーマの CSS を出力から消せる。

mkdir -p assets/css/includes && : > assets/css/includes/chroma-styles.css

確かめるのは設定値ではなく出力の CSS で、chroma の配色ルールが 0 件になっていればよい。

Docker イメージを公式のものに乗り換える

peaceiris/hugo から ghcr.io/gohugoio/hugo に乗り換えると bash が無く、WORKDIR は /project で uid 1000 の hugo ユーザで動くので、bash -c を sh -c に直す

Docker で Hugo を動かしていたので、イメージも替える必要があった。使っていたサードパーティのイメージ (peaceiris/hugo) は 0.146.4 で配布が止まっている。そこで公式のイメージ ghcr.io/gohugoio/hugo (GitHub Packages) に乗り換えた。

v0.167.0 を起動して確かめた中身は次のとおり。

  • entrypoint は /bin/sh のスクリプト (exec hugo "$@")。bash は入っていない
  • WORKDIR は /project
  • extended 版で、Hugo Modules に要る go と git は入っている
  • uid 1000 の hugo ユーザで動く

Makefile や compose の bash -c を sh -c に、マウント先を /project に直した。bash 前提のヘルパーは sh で書き直した。docker compose run ... bash のようなコンソールの起動も動かなくなる。マウントしたディレクトリの所有者が uid 1000 でないと、書き込みで失敗しうる点も気にしておく。

まとめ:ビルドが通った後に確かめること

ビルドが通った後に、ページャの件数、見出しの綴り、複数回ビルドの差分、出力の CSS の 4 つを確かめる

古い Hugo を上げるときは、ビルドエラーを直し終えた時点ではまだ半分だ。

  • ページャの件数: paginate を pagination.pagerSize に移したか
  • タグ・セクションの見出しの綴り: capitalizeListTitles と、大小違いのタグ
  • 3 回ビルドして見出しの集合を diff する: ビルドごとに揺れるものを拾う
  • 出力の CSS: テーマの設定が効いているかは、設定値でなく結果で見る

旧版の出力を手元に残し、新版と並べて見比べられる状態を作ってから上げると、この 4 つを順に潰せる。

Hugo のテンプレートや設定の仕組みを最初から押さえておきたいなら、入門書が 1 冊あると上書きテンプレートを読むときに迷いにくい。

Hugoで始める静的サイト構築入門 (meganii 著、技術の泉シリーズ) 画像: 楽天市場

Hugoで始める静的サイト構築入門 (meganii 著、技術の泉シリーズ)

参考