Hugoの site と .Site の違いと正しい活用方法

JavaScriptを有効にしてください

まえがき

Hugoのテンプレートは、Go言語のテンプレート機能を利用しています。
しかし、Go言語のテンプレート機能は、初心者にとってはやや理解しづらく、使いにくい部分もあります。
特に、内部の仕組みが分からないと、どのように動作しているのか把握しづらいかもしれません。

本記事では、Hugoのテンプレート内で使用できる変数について解説し、特に site.Site の違いを分かりやすく説明します。

site.Site

テンプレートで Params 変数を参照する機会は多いと思います。
さまざまなサイトを見ると、以下のように2種類の書き方が使われているのに気づくでしょう。

1
2
3
<p>site と .Site</p>
<p>{{ site.Params.myname }}</p>
<p>{{ .Site.Params.myname }}</p>

どちらの書き方も同じ Params 変数にアクセスしていますが、site はどこからでも参照できるのに対し、.Site はテンプレートに渡されたコンテキストに依存します。

  • site
    テンプレート内のどこからでも参照可能なグローバルな存在です。
    厳密には変数ではなく、関数として定義されており、関数内部で Site 変数を取得して返却しています。

  • .Site
    テンプレートに渡されたコンテキストから参照されます。
    そのため、.Site が利用可能かどうかは、テンプレートに渡されたコンテキストに依存します。

コンテキストについて

テンプレートでの「コンテキスト」とは、テンプレートに渡されるデータの塊のことを指します。

コンテキストの基本概念

  • データの集合体
    コンテキストは、テンプレートにレンダリングするためのデータ(ページ情報、サイト情報、パラメータなど)が格納されているオブジェクトです。Hugoでは、ページ固有の情報やグローバルなサイト情報がコンテキストとして渡されます。

  • .(ドット)の役割
    テンプレート内で使われる.(ドット)は、現在のコンテキストを表します。例えば、.Site.Params といった書き方は、現在のコンテキスト内からそれぞれ SiteParams を取り出すことを意味しています。

partial内にHTMLテンプレートを作成して試してみる

実際に試してみないとピンとこないかと思いますので、簡単なテンプレートを作成して動作を確認してみましょう。

まず、layouts/partials/body フォルダに test.html というテンプレートを作成します。

1
2
3
<p>site と .Site</p>
<p>{{ site.Params.myname }}</p>
<p>{{ .Site.Params.myname }}</p>

作成したテンプレートを、_default フォルダ内の適当なテンプレートから呼び出します。

1
{{ partial "body/test" . }}

この場合、最後の .test テンプレートに渡すコンテキストとなります。

こちらで実行すると、下記のような表示になるはずです。
(私は本記事のまえがき部分の上に表示されるように埋め込みました。)

siteと.Siteの動作確認

どちらも問題なく参照できていることが確認できるでしょう。

では、次に渡すコンテキストを . から .Site に変更してみましょう。

1
{{ partial "body/test" .Site }}

すると、今度は下記エラーになりました。

execute of template failed at <.Site.Params.myname>: can’t evaluate field Site in type
(テンプレートの実行が <.Site.Params.myname> で失敗しました: 型に対してフィールド Site を評価できません)
siteと.Siteの動作確認(エラー)

これは渡されているコンテキストの中に.Siteがないために発生しています。
test.htmlを下記のように修正してみましょう。

1
2
3
<p>site と .Site</p>
<p>{{ site.Params.myname }}</p>
<p>{{ .Params.myname }}</p>

今度はエラーが解消され問題なく参照出来たかと思います。

このようにsiteはどのようなコンテキストが渡されていても参照できますが、.Siteは渡されているコンテキストにSiteがないと参照できません。

site.Site のどちらを使うべきか?

基本的には .Site を使うのが一般的です。
なぜなら、.Site はテンプレートに渡されたデータからサイト情報を取り出すので、使う場所によって結果が安定しているからです。
難しいかもですが、データフローが明確になるためです。

Hugo内では、site から参照しても .Site から参照しても、通常は取得するデータに違いはありません。しかし、Go言語のプログラム的なお作法としては、コンテキスト内から明示的に参照する .Site を使う方が正しいとされています。

一方、site を使うケースとしては、たとえばテンプレートが深い階層にあり、.Site が利用できるコンテキストが存在しない場合などが挙げられます。この場合、上位階層から渡されるコンテキスト全体を修正する手間を避けるため、やむを得ず site を使うことになります。

変数のピリオドを省略して小文字にすると、すべてグローバルで使用できるの?

他の変数も同様にピリオドを省略して小文字にするとグローバルに使用できると誤解されがちですが、これは間違いです。
site は、Hugo の開発者が利便性を考慮して登録した関数名であり、すべての変数がグローバルに利用できるわけではありません。

グローバルに使用可能な変数の一覧は、下記のページ(英語)に記載されています。
Hugo - functions/global

あとがき

最初は、なぜ二つの書き方が存在するのか分からず、なんとなく使っていました。
しかし、違いを理解すると、どのように使い分ければよいか迷わなくなり、テンプレートの仕組みを活かして柔軟にコードを書くことができるようになりました。

Hugoを使いこなすには、コンテキストの概念をしっかり理解することが重要です。
本記事が、その理解の手助けになれば幸いです。

記事内容でご不明な点がございましたら、下記Xアカウントにお気軽にDMください。
もふもふ-Xアカウント


スポンサーリンク

共有

もふもふ

プロフィール

著者
もふもふ
プログラマ。汎用系→ゲームエンジニア→Webエンジニア→QAエンジニア