久しぶり(約5ヶ月ぶり)に記事を書こうとしたら、 Hugo でのサイトビルド時にエラーが出るようになっていた件について。
エラー自体は Hugo のサポートにも質問が挙がっていてすぐに解消はしたのだが、内部テンプレートについて確認したりしたのでその辺りをまとめる。
エラーの内容
ローカルでビルドした際の実際の出力としてはこんな感じ。
❯ hugo server -D
Watching for changes in /home/shida/src/github.com/goshida/blog/{archetypes,content,layouts,static,themes}
Watching for config changes in /home/shida/src/github.com/goshida/blog/config.toml
Start building sites …
hugo v0.120.1+extended linux/amd64 BuildDate=unknown
ERROR render of "term" failed: template: _internal/_default/rss.xml:3:9: executing "_internal/_default/rss.xml" at <site>: can't evaluate field email in type string
ERROR render of "home" failed: template: _internal/_default/rss.xml:3:9: executing "_internal/_default/rss.xml" at <site>: can't evaluate field email in type string
ERROR render of "taxonomy" failed: template: _internal/_default/rss.xml:3:9: executing "_internal/_default/rss.xml" at <site>: can't evaluate field email in type string
Built in 155 ms
Error: error building site: render: failed to render pages: render of "taxonomy" failed: template: _internal/_default/rss.xml:3:9: executing "_internal/_default/rss.xml" at <site>: can't evaluate field email in type string
書いている通りではあるが、 email
とかいうフィールドの評価ができないから各種ページのレンダリングができないよ、らしい。
解消方法
Hugo のサポートにまんまこの件の質問が挙がっていた。
Render of “section” failed – cannot find the template that has the error - support - HUGO
バージョンアップに伴って破壊的な変更があったらしく、この一連の会話の通り config.toml
で
[params]
author = 'goshida'
と設定していたところを、
[params.author]
name = 'goshida'
とすることで解消した。
( email
は元々設定していない)
内部テンプレートの確認
上記の通りビルドエラー自体はすぐに解消したが、具体的にどういうことだったのか、ということで内部テンプレートの中身も見てみた。
まず v0.120.1
時点での _internal/_default/rss.xml
とかいう内部テンプレートがどういう記述になってるのかという話だが、以下に置いてある。
ソースを取ってきて diff を見ていったところ、 v0.119.0
から v0.120.0
の間で色々変更されていた。
❯ git diff v0.119.0 v0.120.0 ./tpl/tplimpl/embedded/templates/_default/rss.xml
diff --git a/tpl/tplimpl/embedded/templates/_default/rss.xml b/tpl/tplimpl/embedded/templates/_default/rss.xml
index 4bdd844b3..12756e781 100644
--- a/tpl/tplimpl/embedded/templates/_default/rss.xml
+++ b/tpl/tplimpl/embedded/templates/_default/rss.xml
@@ -1,39 +1,61 @@
-{{- $pctx := . -}}
-{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
-{{- $pages := slice -}}
-{{- if or $.IsHome $.IsSection -}}
-{{- $pages = $pctx.RegularPages -}}
-{{- else -}}
-{{- $pages = $pctx.Pages -}}
-{{- end -}}
-{{- $limit := .Site.Config.Services.RSS.Limit -}}
-{{- if ge $limit 1 -}}
-{{- $pages = $pages | first $limit -}}
-{{- end -}}
+{{- /* Deprecate site.Author.email in favor of site.Params.author.email */}}
+{{- $authorEmail := "" }}
+{{- with site.Params.author.email }}
+ {{- $authorEmail = . }}
+{{- else }}
+ {{- with site.Author.email }}
+ {{- $authorEmail = . }}
+ {{- warnf "The author key in site configuration is deprecated. Use params.author.email instead." }}
+ {{- end }}
+{{- end }}
+
+{{- /* Deprecate site.Author.name in favor of site.Params.author.name */}}
+{{- $authorName := "" }}
+{{- with site.Params.author.name }}
+ {{- $authorName = . }}
+{{- else }}
+ {{- with site.Author.name }}
+ {{- $authorName = . }}
+ {{- warnf "The author key in site configuration is deprecated. Use params.author.name instead." }}
+ {{- end }}
+{{- end }}
+
+{{- $pctx := . }}
+{{- if .IsHome }}{{ $pctx = .Site }}{{ end }}
+{{- $pages := slice }}
+{{- if or $.IsHome $.IsSection }}
+{{- $pages = $pctx.RegularPages }}
+{{- else }}
+{{- $pages = $pctx.Pages }}
+{{- end }}
+{{- $limit := .Site.Config.Services.RSS.Limit }}
+{{- if ge $limit 1 }}
+{{- $pages = $pages | first $limit }}
+{{- end }}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
- <title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
+ <title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }}</title>
<link>{{ .Permalink }}</link>
- <description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
+ <description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{ . }} {{ end }}{{ end }}on {{ .Site.Title }}</description>
<generator>Hugo -- gohugo.io</generator>
- <language>{{ site.Language.LanguageCode }}</language>{{ with .Site.Author.email }}
- <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
- <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
- <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
+ <language>{{ site.Language.LanguageCode }}</language>{{ with $authorEmail }}
+ <managingEditor>{{.}}{{ with $authorName }} ({{ . }}){{ end }}</managingEditor>{{ end }}{{ with $authorEmail }}
+ <webMaster>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</webMaster>{{ end }}{{ with .Site.Copyright }}
+ <copyright>{{ . }}</copyright>{{ end }}{{ if not .Date.IsZero }}
<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
- {{- with .OutputFormats.Get "RSS" -}}
+ {{- with .OutputFormats.Get "RSS" }}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
- {{- end -}}
- {{ range $pages }}
+ {{- end }}
+ {{- range $pages }}
<item>
<title>{{ .Title }}</title>
<link>{{ .Permalink }}</link>
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
- {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
+ {{- with $authorEmail }}<author>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</author>{{ end }}
<guid>{{ .Permalink }}</guid>
<description>{{ .Summary | html }}</description>
</item>
- {{ end }}
+ {{- end }}
</channel>
</rss>
上記の通り v0.119.0
以前の内部テンプレートでは単純に .site.Author.email
の値を出力していた(設定されていなければ出力しない)のだが、
v0.120.0
以降の内部テンプレートでは、それに加えて .site.Params.author.email
も見るようになった。
ところが、前述の通り元々 .site.Params.author
をキーとした値を設定していたため、
テンプレートが .site.Params.author.email
(TOML的に不正な値)を参照しようとするのでエラーになっていた、ということっぽい。
ちなみにこういうパターンが TOML 的に不正、というのも今回知った。
# 以下は不正となります。
a.b = 1
a.b.c = 2
また、これもテンプレートに書いてある通りだがこれまで Hugo では以下のような設定も使われていた。
[author]
name = 'hoge'
email = '[email protected]'
こういった設定もまだ有効ではあるものの、そのうち廃止する予定なのでこれからは params
以下に設定してね、とのこと。
[params.author]
name = 'hoge'
email = '[email protected]'
自分は割とググりながら行き当たりばったりでガチャガチャしがちなので、自前のテーマでうっかり廃止予定の形のパラメータを要求しない様に注意しておく必要がありそう。
RSS の項目としてメールアドレスは出した方が良いのか
今回エラーが出たテンプレートは RSS 用のURLにあたる <サイトドメイン>/index.xml
を出力する内部テンプレートでのエラーになる。
これまで意識してなかったのだが、今回みたいにエラーとして意識する機会があると「RSS の項目としてメールアドレスって出さなくても良いのか?」というのが気になってくる。
前述の Hugo のサポートでの回答でも「 SEO 的な評価要素では無いよ」と触れられてはいたが、せっかくなので RSS の仕様も見てみる。
RSS 2.0 Specification (Current)
オプショナルな項目で特に推奨といった記載もなく、個人のブログなら省略するのが理に適っている(どちらかと言うとむしろ出さない方が自然?)、ということらしい。 このサイトの連絡先メールアドレス的なものが決まったらとりあえず設定しようかとも思っていたのだが、 何処で使われているかを確認してから考えるのが良さそう、という感じだった。
おわりに
自分は、自分が使ってるツールやライブラリでもリリースノートとかを追う習慣があまり身に付いて無く、今回の様に何か困ったことがあったら見てみる感じになっているのだが、 その度にリリースノートをちゃんと見る習慣を付けた方が良いんだろうかということを思ったりしている。
ちゃんと追うのが理想だろうとは思うものの、使っているツールの開発規模とか量次第では現実的に無理じゃねという気持ちもあり、 世のエンジニアはどういうスタンスなんだろうな、ということを改めて思った次第。 (まぁケースバイケースという話にしかならないかも知れないが)