参照サイト
Template lookup order
Hugo uses the rules below to select a template for a given page, starting from the most specific.
この記事では Docsy テーマを題材としているが、考え方はその他のテンプレートでも適用可能。ただし、Hugo の テーマはそれぞれで実装方法の特色があり、(例えば WordPress のように)共通部品が整っているわけではないので注意する必要がある。
https://github.com/google/docsy/blob/v0.5.1/layouts/partials/head.html
layouts/partials/head.html
{{ if and hugo.IsProduction (ne $outputFormat "print") -}}
<meta name="robots" content="index, follow">
{{ else -}}
<meta name="robots" content="noindex, nofollow">
{{ end -}}
layouts/partials/head.html
は Docsy により生成された各種ページで共通的に用いられている head
タグ内の構成データである。v0.5.1 (2022/11/03) 現在、noindex を柔軟に挙動を変更する手段はない。
themes/
ディレクトリに Docsy テーマを直接配置していている場合は、直接上書きしてしまえば当然だが簡単に挙動を変えることができる。しかしこの場合、Docsy テーマのアップデート(バージョンアップ)時には毎回、独自にカスタマイズした内容を反映しなければならず作業工数が発生してしまうのが欠点。そのため Hugo のベストプラクティスとしては外部のテーマ ( themes/
ディレクトリ内のテーマ、あるいは Hugo module により読み込んだデータ)はオリジナルのまま変更せず、自身のサイト生成のためのローカルファイル( layouts/
)内に同名のファイルを配置して上書きするのが良い。
Hugo テンプレートの読み込み順序の仕様を活用して、上書きしたい部分を選定する。
Hugo uses the rules below to select a template for a given page, starting from the most specific.
今回の場合、Docsy オリジナルの latouts/partials/head.html
を分解しなければならない。今後のメンテナンスを効率的にするためにも、 noindex 関連の処理は別ファイルに分離することとする。
layouts/partials/head.html
{{ partial "noindex.html" . }}
としている部分がミソ{{- /* Tag ページを Noindex にしたかったので Override */ -}}
{{- /* Original: https://github.com/google/docsy/tree/v0.5.1/layouts/partials */ -}}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{{ hugo.Generator }}
{{ range .AlternativeOutputFormats -}}
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
{{ end -}}
{{ $outputFormat := partial "outputformat.html" . -}}
{{ partial "noindex.html" . }}
{{ partialCached "favicons.html" . }}
<title>
{{- if .IsHome -}}
{{ .Site.Title -}}
{{ else -}}
{{ with .Title }}{{ . }} | {{ end -}}
{{ .Site.Title -}}
{{ end -}}
</title>
<meta name="description" content="{{ template "partials/page-description.html" . }}">
{{ template "_internal/opengraph.html" . -}}
{{ template "_internal/schema.html" . -}}
{{ template "_internal/twitter_cards.html" . -}}
{{ partialCached "head-css.html" . "asdf" -}}
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK"
crossorigin="anonymous"></script>
{{ if .Site.Params.offlineSearch -}}
<script defer
src="https://unpkg.com/lunr@2.3.9/lunr.min.js"
integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli"
crossorigin="anonymous"></script>
{{ end -}}
{{ if .Site.Params.prism_syntax_highlighting -}}
<link rel="stylesheet" href="{{ "css/prism.css" | relURL }}"/>
{{ end -}}
{{ partial "hooks/head-end.html" . -}}
{{/* To comply with GDPR, cookie consent scripts places in head-end must execute before Google Analytics is enabled */ -}}
{{ if hugo.IsProduction -}}
{{ $enableGtagForUniversalAnalytics := not .Site.Params.disableGtagForUniversalAnalytics -}}
{{ if (or $enableGtagForUniversalAnalytics (hasPrefix .Site.GoogleAnalytics "G-")) -}}
{{ template "_internal/google_analytics_gtag.html" . -}}
{{ else -}}
{{ template "_internal/google_analytics_async.html" . -}}
{{ end -}}
{{ end -}}
layouts/partials/noindex.html
{{ if or (eq .Params.Noindex true) (eq .Kind "section") (eq .Section "tags") }}
としている部分で tags
を noindex, follow
としている.Params.Noindex
は、コンテンツ(記事)の FrontMatter で noindex: true
をしている場合には、その記事のみを noindex にできるeq .Kind "section"
は、section のトップページ(記事の一覧を表示する部分)を noindex にしたいケースeq .Section "tags"
は、今回の目的である Tag 一覧ページで noindex にしたいケース{{ if or (eq .Params.Noindex true) (eq .Kind "section") (eq .Section "tags") }}
<meta name="robots" content="noindex, nofollow">
{{ else }}
{{ if hugo.IsProduction }}
<meta name="robots" content="index, follow">
{{ else }}
{{ "<!-- [DEBUG] meta robots is follow in Production -->" | safeHTML }}
<meta name="robots" content="noindex, nofollow">
{{ end }}
{{ end }}
上記コードをベースにして、除外したい条件を指定することで挙動を変更することができる。
その他、If文で判定したいパラメタの一例は以下の記事も参照。
前述「1」の対応により完了となるが、自身のカスタマイズの適用範囲を最小限にしたいケースも考えられる。例えば以下の例:
その場合は以下の対応とする。
layouts/partials/head.html
として Docsy と同名で上書きしたファイルを、重複しない別ファイルに分離する。
layouts/partials/docsy/head.html
とするのがシンプルでよいlayouts
ディレクトリ直下に tags
ディレクトリを新規作成し、このディレクトリ内に上書きしたいテンプレートを配置する
layouts/tags/baseof.html
を作成して以下のコンテンツを作成する<head>
内部で読み込んでいる partial を docsy/head.html
としている<!doctype html>
<html itemscope itemtype="http://schema.org/WebPage" lang="{{ .Site.Language.Lang }}" class="no-js">
<head>
{{ partial "docsy/head.html" . }}
</head>
<body class="td-{{ .Kind }}{{ with .Page.Params.body_class }} {{ . }}{{ end }}">
<header>
{{ partial "navbar.html" . }}
</header>
<div class="container-fluid td-default td-outer">
<main role="main" class="td-main">
{{ block "main" . }}{{ end }}
</main>
{{ partial "footer.html" . }}
</div>
{{ partialCached "scripts.html" . }}
</body>
</html>
Original source: v0.5.1 https://github.com/google/docsy/blob/v0.5.1/layouts/partials/head.html
このファイルも Hugo のバージョンアップ時には変更を反映しなければならないが、コード量が少なく、更新頻度は低いと思われるので許容可能な範囲として妥協。
やはり Hugo’s Lookup Order の理解が重要なので、柔軟なカスタマイズのためには概要を抑えておきたいところ。