UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

HUGOをプロダクションに使ったりNetlifyに入門したりしました

こんにちは、自称Webエンジニアのナカハシです。

最近イベント用のサイトをHUGOで構築しました。

その際感じたHUGOに関するあれこれと、最近(?)話題のNetlifyをHUGOで利用してみた感想を書いてみたいと思います。

HUGOってなに?

https://gohugo.io/

HUGOは、GO言語製の静的サイトジェネレーターです。

とHUGOの紹介をしようと思ったのですが ...

実は、2年以上前にこのブログでHUGO取り上げていたんですね ... 知らなかった 😂 今回の記事とある程度重複しますが、上記の記事もぜひご覧くださいw

私が今回感じたメリットを書いておくと、

  • とにかく速い
  • ある程度枯れているため、(日本語)情報やエコシステムが豊富

という感じです。個人的にGOはちょっとしか書いたことありませんが、ツールとして使う分にはほとんど困りませんでした。

構築したサイトの要件

さて、今回HUGOで開発したサイトの要件ですが、以下のようなものでした。

  1. 記事一覧
  2. 記事内容
  3. タグ
  4. タグごとの一覧
  5. 記事一覧自体を大分類化
  6. GA

これらは全て、HUGOの標準機能で簡単に実現可能です。

記事一覧のように動的に記事を取得する場合には、Go templateのシンタックスでHTML内に VariablesFunctions を使って条件を付けて行います。

たとえば、記事を単純に列挙する場合は、

<ul>
  {{ range .Data.Pages }}
    <li><a href="{{.Permalink}}">{{.Title}}</a></li>
  {{ end }}
</ul>

と、 {{ }} に全ページを列挙する Data.pages を入れます。

これを日付順に並び変えるには、

<ul>
  {{ range .Data.Pages.ByDate }}
    <li><a href="{{.Permalink}}">{{.Title}}</a></li>
  {{ end }}
</ul>

と、 ByDate を追加するだけで実現できます。

サイト内の特定のタグ(例えば game というタグを持つ記事)を列挙する場合は、

<ul>
  {{ range .Site.Taxonomies.tags.game }}
    <li><a href="{{.Permalink}}">{{.Title}}</a></li>
  {{ end }}
</ul>

となります。 Taxonomies.tags 部分がタグ指定を意味するVariablesです。

記事はMarkdownで書くことができ、

---
title: こんなゲーム出るよ!!
date: 2018-03-21T00:24:10+09:00
tags: ["game"]
---

# こんなゲーム出るよ!!

* あんなゲーム
* こんなゲーム

といった形で、タイトルやタグなどのメタデータを指定できます。

GA対応ですが、サイト設定全体を行うconfig.ymlというファイルがあるのでここに、

googleAnalytics: UA-xxxxxxxx

と設定し、テンプレートファイル内で

{{ template "_internal/google_analytics_async.html" . }}

唱えればいいだけです。 googleAnalytics を設定しなければ、GA用タグはビルド内容から外れるだけです。

Hugoは、上記のようにGo templateで書いたHTMLによるレイアウトファイルと、Markdownで書いた記事ファイルを結合し、いい感じにHTMLを出力(ビルド)してくれます。

デプロイ

さて、Hugoが出力したファイルのデプロイですが、今回は歴史的な経緯もあって、AWS S3の静的ウェブサイトホスティング機能で公開することにしました。

手元で記事を編集した後にS3への転送コマンドを叩いてもいいのですが、記事編集を非エンジニアが行う*1というユースケースを考慮し、今回はCircleCIによる自動ビルド~デプロイを行うことにしました。

.circleci/config.yml では、 hugo コマンド(及びsassやbabelなど)でビルドを実行後するようにし、出力されたHTML群を以下のようなfabfile.pyでデプロイするスクリプトを書きました。

env.src_dir = 'public'
env.dist_dir = 'dist_dir'

@task
def deploy():
    _rsync()

def _rsync():
    local('aws s3 sync --delete --region ap-northeast-1 %(src_dir)s s3://s3_bucket/%(dist_dir)s' % env)

Hugoはビルド結果を public というディレクトリに出力するので、その内容をS3に出力するよう、 aws s3 コマンドを実行しています。

今回はCloudFrontによるCDN配信も行っていますが、デプロイ時にはキャッシュをクリアするよう、CircleCI内で以下のコマンドを実行しています。

aws configure set preview.cloudfront true
aws cloudfront create-invalidation --distribution-id ${CLOUDFRONT_DISTRIBUTION_ID} --paths '/*'

これでめでたく、Git push → Hugoによるビルド → S3へのデプロイができるようになりました。

Netlifyって?

https://www.netlify.com/

さて、最近静的サイトのホスティングでは、Netlifyを使う例が増えてきているようです。Hugoを使ったサイトの公開を試してみることにしました。

公開

まず、とりあえず公開してみましょう。手順は超簡単でした。

  1. GitHubにHugoで作ったサイトをpushする(ビルド結果はここに含めなくてよい)
  2. Netlifyでサイト新規作成し、1.で作ったリポジトリを指定
  3. 「Deploy site」ボタン押す

なんとこれで終了。ビルド~デプロイにかかる時間は約10秒(CircleCIで実行した場合は2~3分程度かかる)。爆速過ぎます。

※ 私の場合、使ったテーマの問題なのかHugoビルドがうまくいきませんでした。その場合、手元のクライアントでビルドした時と同じHugoのバージョンを環境変数で以下のように設定するといいようです。

HUGO_VERSION=0.37.1

HTTPS

HTTPSも超簡単です。

  1. ドメインとる(今回は freenom で取ってみました)
  2. DNSにNetlifyのサーバーを指定(freenom の場合は、ドメイン管理画面内で行えました)
  3. Netlifyの管理画面内の「SSL/TLS certificate」に周辺設定を行う(ドメイン確認や証明書配置など、段階に応じてボタンが変わるので、それを押していくだけ)

たったこれだけで、HTTP → HTTPSの転送も含めたHTTPSによるサイト公開ができました。

証明書は、Netlifyが自動的にLet’s Encryptを使って配置してくれます(更新も自動)。証明書の種類にこだわる向きには、持ち込みの証明書にも対応しているようです。

まとめ

単純なコンテンツサイトを構築しようという場合、頑張ってWordPressとか立てるのがあほらしくなるくらい、HugoやNetlifyは便利です。

node_modulesのようなフロントエンドの技術スタックも問題なく使えるので、コーディングの上での制限も少ないといえます。

必要に応じて、バシバシ使っていきましょう。

*1:この場合、GitHub上のエディタで直接記事を作成・マージしてもらう運用にしました。