HugoとTailwind CSSで静的サイトの作成準備をする

7 min read読了の目安(約7000字

概要

Hugoで静的サイトを作り始めるため、ざっくりとしたテンプレートを1から作成する。

この記事で行うこと

  • Hugoのテンプレート作成準備
  • Hugo用のざっくりとしたテンプレートを作成
  • Tailwind CSSの使用準備(WebpackPost CSSでビルド)

環境

Hugo v0.77.0
{
  "devDependencies": {
    "autoprefixer": "^10.0.1",
    "css-loader": "^5.0.1",
    "postcss": "^8.1.4",
    "postcss-loader": "^4.0.4",
    "sass": "^1.29.0",
    "sass-loader": "^10.0.5",
    "style-loader": "^2.0.0",
    "tailwindcss": "^1.9.6",
    "webpack": "^5.4.0",
    "webpack-cli": "^4.2.0"
  }
}

覚え書き

Hugo

The world’s fastest framework for building websites | Hugo

Go製の静的サイトジェネレータ。コマンドを叩くと処理のいちいちが速い。

氷砂糖はGoのことがほとんど分からないが、Goの知識が分からないことで躓くことはほとんど無かった(Goでの実装を方法を探していたらHugoのサイトにHugoの実装として答えが載っていたことがある)。

既存テーマを使うならともかく、1からテンプレートを作ろうと思うと個人的には読みにくいリファレンス(文字が多くて辞書っぽい作りのためそう感じる?🤔 あと出来ることが多くて量が多い)を全体的に読んでいく必要がある。しかし、Hugoの基本機能で表現したいことの大部分がカバーできたため一度覚えてしまうと使い勝手がよかった。

使う前はなぜかブログに強いイメージがあったが、ブログでもドキュメントでもこなせるし、1ページ1ページが違うデザインのサイトでも無理なく対応可能そうだった。

Tailwind CSS

Tailwind CSS - A Utility-First CSS Framework for Rapidly Building Custom Designs

1からスタイルを付けていくのに便利なCSSライブラリ。例えば「背景色をグレーにしたい」場合はbg-gray-500のようなクラスを要素に追加する。

好意的に書かれている記事をよく見かけるので使ってみたくなるのだが、Post CSSの知識がないと 「そもそもどうやって導入したらいいのか分からない」 という状態になるかもしれない🙄

テンプレートの準備

スケルトンの作成

任意のディレクトリでhugo new site myblogを実行し、サイトのスケルトンを作成する(myblogは好きな名称でよい)。

hugo new site myblog

サーバの起動

先程作成したディレクトリ内に移動し、hugo server -Dでサーバを起動する。

cd myblog
hugo server -D

-Dオプションが付いているとき、下書き状態の記事(Front Matterのdrafttrueの記事)が表示される。

テスト用コンテンツの作成

作成中のテンプレートが確認がしやすいように、適当な記事を作成する。

hugo new posts/my-first-post.md
hugo new posts/my-second-post.md
hugo new posts/my-third-post.md

hugo new posts/my-first-post.mdを実行するとcontent/posts/my-first-post.mdに記事が作成されるが、postsを好みでarticles等にしてもよい(その場合テンプレートや設定ファイルは若干の修正が必要になるかもしれない)。

コンテンツの格納場所(content)を変更したい場合は、設定ファイルのcontentDirで指定する(参考:Configure Hugo | Hugo)。

テンプレートの作成

ベーステンプレート

各テンプレートのベースとなるテンプレートをlayouts/_default/baseof.htmlに作成する。

<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ .Site.Title }}</title>
  </head>
  <body>
    <h1>
      <a href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a>
    </h1>
    <div>
      {{ block "main" . }}{{ end }}
    </div>
  </body>
</html>

参考

リストテンプレート

記事の一覧用のテンプレートをlayouts/_default/list.htmlに作成する。

{{ define "main" }}
  <ul>
    {{ range .RegularPages }}
      <li>
        <a href="{{ .Permalink }}">{{ .Title }}</a>
      </li>
    {{ end }}
  </ul>
{{ end }}

{{ define "main" }}{{ end }}を使用することで、ベーステンプレートの内容を取り込める(defineを使用せずにhtml要素から書いていくことも可能)。

参考

シングルページテンプレート

記事の単体表示用のテンプレートをlayouts/_default/single.htmlに作成する。

{{ define "main" }}
  <article>
    <header>
      <h1>{{ .Title }}</h1>
      <div>{{ .Date.Format "January 2, 2006" }}</div>
    </header>
    <div>{{ .Content }}</div>
  </article>
{{ end }}

参考

ホームページテンプレート

サイトのトップページ(ホームページ)で使用するテンプレートをlayouts/index.htmlに作成する。

{{ define "main" }}
  <ul>
    {{ range (where .Site.RegularPages "Section" "posts") }}
      <li>
        <a href="{{ .Permalink }}">{{ .Title }}</a>
      </li>
    {{ end }}
  </ul>
{{ end }}

where .Site.RegularPages "Section" "posts"は、サイト全体の記事でSection(ディレクトリのようなもの)がpostsのものを絞り込むという処理になる。hugo new posts/my-first-post.mdで作成した記事は取得できるが、例えばhugo new hoge/my-first-post.mdで作成した記事は取得できない。

参考

Tailwind CSSの導入

テンプレートのデザイン用にTailwind CSSを導入する。

Hugo自体にもPostCSS等を処理する仕組みがあるが、テンプレートを作るたびにその部分で躓くため、ひとまずWebpackでTailwind CSSのビルドを行う。

パッケージの追加

Tailwind CSSのビルドに必要なパッケージを追加していく。

Webpack

Webpackの使用に必要。

yarn add --dev webpack webpack-cli

css-loaderとstyle-loader

css-loader@importurl()を解決し、style-loaderはDOMにCSSを注入する。

yarn add --dev css-loader style-loader

場合によってはcss-loaderを取り除けるかもしれない🙄(参考:css-loader と style-loaderを間違えない ~css-loaderを使わずにcssを使ってみる~

Sass

Sass(SCSS)の使用に必要(Sassを使わないなら不要🤔)。

yarn add --dev sass sass-loader

Post CSS

Post CSSの使用に必要。

yarn add --dev postcss postcss-loader

Autoprefixer

ベンダープリフィックスをよしなにしてくれる。

yarn add --dev autoprefixer

Tailwind CSS

Tailwind CSSの使用に必要。

yarn add --dev tailwindcss

設定ファイルの作成

webpack.config.jsに設定ファイルを作成する。

今回はsrc/index.jsをエントリポイントにし、assets/bundle.jsにビルド結果を書き出している。

assetsディレクトリはHugoのリソース用のディレクトリ。

const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'assets'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.scss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                ident: 'postcss',
                plugins: [
                  require('tailwindcss'),
                  require('autoprefixer')
                ]
              }
            }
          },
          'sass-loader'
        ]
      }
    ]
  }
}

ソースの作成

エントリポイントのコードから作成していく。

src/index.js

import './css/main.scss'

src/css/main.scss

@tailwind base;
@tailwind components;
@tailwind utilities;

ビルド実行

コマンドを実行してビルドを行う。

yarn webpack

--watchオプションを付けてコマンドを実行(yarn webpack --watch)するとsrc/index.jssrc/css/main.scssの保存時に自動でビルドが走るので、ファイル編集中の確認に便利。

ビルド結果ファイルの読込

ビルドしたJavaScriptファイル(assets/bundle.js)をベーステンプレート(layouts/_default/baseof.html)等に読み込ませる。

<html>
  <!-- ... -->
  <body>
    <!-- ... -->
    {{ $script := resources.Get "bundle.js" }}
    <script src="{{ $script.RelPermalink }}"></script>
  </body>
</html>

resources.Getassetsディレクトリ内のファイルを取得できる。

パーマリンク取得方法にはRelPermalinkの他にPermalinkがある。RelPermalinkだと/bundle.jsのように取得でき、Permalinkだとhttp://localhost:1313/bundle.jsのように取得できる。