Zenn
📌

Hugo で Tailwind CSS を使うための設定

2025/02/10に公開

まえがき

かつて静的サイトジェネレータの HugoTailwind CSS を使おうとするとうまくいかないことがありました。
たとえば hugo server で起動中、新しいクラスを付けてホットリロードしたのに見た目が反映されない……ということが、Hugo だと容易に起こります。
また、それを解決するための設定は一筋縄ではいきませんでした。

しかし最近改めて調べてみたら、去年 Tailwind CSS のためだけに新機能が実装されていました。
現在はそう複雑ではない設定で Tailwind CSS を快適に使うことができますので、今後 Hugo を使う方にご紹介したいと思います。

環境

  • Hugo: v0.142.0
  • Tailwind CSS: v4.0.2

結論

Hugo の開発者の bep 氏が Tailwind CSS 連携のサンプルを作成してくれています。
Tailwind CSS v4 対応のリポジトリは下記です。
https://github.com/bep/hugo-testing-tailwindcss-v4

結論としてはこれを真似れば終わりですが、確認したところ少しだけ不要な記述が含まれていたので、本記事向けに上記サンプルリポジトリの "TailwindCSS CLI Defer" のパターンで実装しました。私のサンプルリポジトリは下記です。
https://gitlab.com/k1350/hugo-tailwindcss

この後は私なりに何をやっているかの解説を挟んでいきたいと思います。

実装について詳しく

やることは2点です。

  • templates.Defer で Tailwind CSS CLI の処理を遅延する
  • 適宜 css ファイルのキャッシュを削除する

templates.Defer で Tailwind CSS CLI の処理を遅延する

Hugo で Tailwind CSS CLI を動かすために css.TailwindCSS という機能が存在しますので、これを使います。
package.json の scripts には何も書く必要はありません。@tailwindcss/cli が dependencies/devDependencies に入っていてインストール済みであればいいです。

全文は長いので サンプルリポジトリ をご参照いただくとして、該当部分だけ下記に抜粋します。

layouts/_default/baseof.html
<head>
  <!-- 中略 -->
  {{ with (templates.Defer (dict "key" "global")) }}
    {{ with resources.Get "css/styles.css" }}
      {{ $opts := dict
        "inlineImports" true
        "optimize" (not hugo.IsDevelopment)
      }}
      {{ with . | css.TailwindCSS $opts }}
        {{ if hugo.IsDevelopment }}
          <link rel="stylesheet" href="{{ .RelPermalink }}" />
        {{ else }}
          {{ with . | minify | fingerprint }}
            <link
              rel="stylesheet"
              href="{{ .RelPermalink }}"
              integrity="{{ .Data.Integrity }}"
              crossorigin="anonymous" />
          {{ end }}
        {{ end }}
      {{ end }}
    {{ end }}
  {{ end }}
</head>

templates.Defer はブロック内の処理実行をサイト全体のレンダリングが終わるまで遅延させます。
ブロック内では assets/css/styles.css を取得して Tailwind CSS CLI による処理を行っています。

要するに、サイト全体で使用されるクラスが確定してから Tailwind CSS CLI を動かすことができます。

適宜 css ファイルのキャッシュを削除する

Tailwind CSS CLI の処理を遅延させるだけでも問題なく動くように見えるのですが、text-[<value>] のように custom value を使ったときなど、特定のケースで画面が更新されない場合があります。
その対策で hugo.yaml で次の設定を行います。

hugo.yaml
baseURL: 'https://example.org/'
languageCode: 'en-us'
title: 'My New Hugo Site'

module:
    hugoVersion:
        min: "0.128.0"
    mounts:
        - source: assets
          target: assets
        - source: hugo_stats.json
          target: assets/notwatching/hugo_stats.json
          disableWatch: true
build:
    buildStats:
        enable: true
    cachebusters:
        - source: assets/notwatching/hugo_stats\.json
          target: styles\.css

まず build.buildStats を有効にします。
これを有効にするとルートディレクトリに hugo_stats.json というファイルが生成されるようになります。
hugo_stats.json にはサイト内で使用されている HTML タグ、クラス名、ID 名が記載されます。

次に module.mounts でルートディレクトリの hugo_stats.json を assets ディレクトリにマウントします。
disableWatch: true を指定しておくことで、hugo server 中に hugo_stats.json が変更されるたびに再度リビルドしてしまうことを防止します。
ドキュメントに

When you add a mount, the default mount for the concerned target root is ignored: be sure to explicitly add it.

と書いてある通り、target: assets/notwatching/hugo_stats.json の設定を追加するとデフォルトの target: assets へのマウント設定が消えるので、それも追加しています。

最後に build.cachebustersassets/notwatching/hugo_stats.json の変更を検知して style.css のキャッシュを無効化します。

以上を総合すると、hugo server で HTML タグ、クラス名、ID 名等の変更を検知したら style.css のキャッシュが消えるようになります。
その結果、クラスの変更が正しく画面に反映されるようになります。

終わりに

インターネット上には「Hugo で Tailwind CSS を使う方法」の解説記事がたくさんあるのですが、Hugo の開発速度が速いため、古いものを参考にするとハマります。
たとえば templates.Defer と css.TailwindCSS は 2024/06/26 にリリースされた Hugo v0.128.0 で追加されたもので、これらの機能が出る前の記事を参考にすると無駄に面倒な設定を行うことになります。
新しい機能を使って快適にサイトを作りましょう!

chot Inc. tech blog

Discussion

ログインするとコメントできます