(-> % read write unlearn)

All opinions expressed are solely my own and do not express the views or opinions of my employer.

Golang 製の爆速 Static Site Generator 「Hugo」のはまりポイント12

前回の「Static Site Generator」エントリの続きです。 Static Site Generator の Hugo を使ってみました。 ビルドが爆速なのがすごく良いんですが、いくつかはまったのでまとめておきます。 実際には12個もはまってないんですが。

1. デフォルトのテーマ(theme)が設定されていないのでいきなり起動しても何も表示されない

Hexoの場合

# hexo コマンドのインストール
npm install hexo-cli -g
# 新しいサイトを作成
hexo init blog && cd blog && npm install
# ビルドしてサーバを起動
hexo server

とするだけで、デフォルトで設定されたlandscapeというthemeで起動し、 http://localhost:4000/ を開けばトップページが見れます。

Hugoの場合

# Mac-OSの場合 Homebrew で hugo コマンドをインストール
brew update && brew install hugo
# 新しいサイトを作成
hugo new site bookshelf && cd bookshelf
# ビルドしてサーバを起動
hugo server

という手順を踏んでサーバを起動しただけでは、何も表示されません。 thmemeが何も設定されていないからです。*1

2. テーマ(theme)って何?

デザイン・テンプレートです。 既存のthemeを活用してベースのデザインを作成できます。 もちろんカスタマイズすることができます。 HTMLやCSSやJSなどのファイル群で構成されます。 JekyllやHexoでもthemeという用語を使うので、全然はまりどころじゃないかもしれないですね。

3. themeはGithubなどからcloneしてこないといけない

themeを設定するにはthemesディレクトリ配下に、OSSとしてGitHubに公開されているthemeをgit cloneしてくるのが、最も手っ取り早い方法です。*2

例えば、以下のようにanybodyhomeというthemeをインストールします。

mkdir themes
cd themes
git clone https://github.com/lasseborly/anybodyhome.git

そして、適用するthemeを以下のように指定してサーバを起動します。

hugo server --theme=anybodyhome

これで http://localhost:1313/ ((ローカルの1313ポートが既に使用されている場合は、適当なエフェメラルポートがアサインされます。コマンドの出力で確認してください。))を開けばトップページが表示されます。

4. themeは実はまとめて全てcloneしてこれる。

themesディレクトリにはいくつでもthemeをcloneしておけます。 https://github.com/spf13/hugoThemes リポジトリにはOSSで公開されているthemeがまとまっており、これをcloneすればまとめてインストールできます。

git clone --recursive https://github.com/spf13/hugoThemes.git themes

あとは、hugo server --theme=<試したいtheme名>で色々試してみて気に入ったものを見つけたらconfig.tomltheme = "anybodyhome"などのように記述すればOKです。 起動時に--theme指定がない場合にはconfig.tomlの設定が使用されます。

5. 記事のメタデータの書式がToml

hugo new post/foo.mdと実行すると/content/post/foo.mdという記事のファイルの雛形が生成されます。 このファイルの先頭には、自動でメタデータが書かれています。 こんな感じです。

+++
date = "2016-09-04T16:01:08+09:00"
draft = true
title = "foo"

+++

これはTomlという形式です。 メタデータには、他にcategoriestagsslugなどなどの値があるのですが、 categoriestagsには複数の値が指定でき、その場合はTomlの配列の形式で書きます。 例えばこんな感じです。

+++
date       = "2016-09-04T16:01:08+09:00"
lastmod    = "2016-09-11"
draft      = true
title      = "foo"
categories = ["programming", "golang"]
tags       = ["golang", "toml", "hugo"]
notoc      = true
+++

6. 設定ファイルもToml

config.tomlという見慣れない拡張子のファイルがサイト全体の設定ファイルです。 RustのビルドツールのCargoでも採用されているし、実は結構メジャーなのかもしれません。

  • Tomlの基本の構文は、改行区切りで設定を列記していくかたちです。iniとかに少し近いです。
  • 行コメントの記号は、#です。
  • """"""で囲ってやれば複数行の文字列リテラルとなります。
  • 添字配列は、["apple", "orange", "grape"]のように[]で記述します。
  • Tomlが気に入らない場合はconfig.yamlconfig.jsonなどを用意すればtoml以外の形式も使用可能です。

Tomlは連想配列の構文などもあり、シンプルながらかなり表現力豊かですが、Hugoの設定としては上記を知ってればだいたい大丈夫な気がします。 Tomlの詳しい文法はQiitaにもいくつか投稿されています。

7. 記事のURLの変え方

設定ファイルの[permalinks]以下にpostという設定値を追加すればOKです。 [permalinks]自体がなかったらそれも追加してください。

例えばファイル名の拡張子を除いた文字列をURLに使用するなら:filenameというパラメータを使います。

[permalinks]
  post = "/post/:filename"

日付やメタデータtitle値を使うならこんな感じ。

[permalinks]
  post = "/:year/:month/:title/"

8. テンプレートのカスタマイズ

themeでインストールしたテンプレートをカスタマイズ/拡張し管理する方法は2つあると思います。

1つは、themeの中で使われているテンプレート・ファイルのうち上書きしたいものをlayouts/にコピーし、好きに書き換えることです。 例えば、
themes/anybodyhome/layouts/partials/footer.htmlというファイルは全体のフッタ部分を構成するHTMLのテンプレートです。 これを
layouts/partials/footer.htmlにコピーして編集すればOKです。

ただし、この方法はテンプレート・ファイル単位での上書きになってしまうところがちょっと嫌です。 なぜかというと、さっきのfooter.htmlならまだ良いのですが、記事自体のページのテンプレートのHTMLをほんのちょっと修正したいような場合にもthemes/anybodyhome/layouts/_default/single.htmlという記事全体のHTMLのテンプレートをまるまるコピーしないといけないからです。 適切にHTMLがパーツ化されていて、修正したい部分が小さなパーツになっている場合には悪くないんですが。

2つめは、使用するthemeをGitHub上でフォークして修正し、それをgit cloneして使用する方法です。 こっちのほうが差分が分かりやすくなるので全然おすすめだと思います。

9. GolangTime.timeの日付フォーマット表記が独特

Hugoで採用されているGolangのテンプレートエンジンの構文は、私は初めてだったので全然慣れませんでした。 しかし、既存のthemeを使う分には見よう見まねでも結構なんとかなります。

1点はまったのが日付のフォーマットの変更です。 Javaなんかだと%YYYY-%MMなどのように%を使ってフォーマットを指定しますが、GolangではMon Jan 2 15:04:05 -0700 MST 2006のように実際の日付の値を使用してフォーマットを指定します。

つまり、

Mon Jan 2 15:04:05 -0700 MST 2006

この日時が重要なようです。 1月なのを勝手に2月とか3月にしてはいけません。

例えば、記事のページ内にメタデータで記述したdate値を表示するテンプレートの構文は

{{ .Date.Format "2006/01/02" }}

のようになります。 これは、テンプレートエンジンの仕様というよりはGolangtimeパッケージの仕様のようです。

10. 404ページ

デフォルトだと指定したURLのリソースが見つからない場合用の404ページがありません。*3 GitHub Pages でホストする場合には、layouts/404.htmlを用意しておけばOKです。 404ページとして生成・使用されます。 layouts/404.htmlは単にルートに404.htmlを生成するだけなので、GitHub Pages以外の環境でもWebサーバを適切に設定すれば上記のファイルを404ページとして使用可能です。 詳しくはhttps://gohugo.io/templates/404#automatic-loadingを参照してください。

11. References

もはやはまりどころでは全くないのですが、カスタマイズしたりする時によく参照するリファレンス達です。

URL 説明
https://gohugo.io/overview/configuration 設定項目とデフォルト値の一覧 |
https://gohugo.io/templates/functions/ テンプレートで使用できる関数の一覧
https://gohugo.io/templates/variables テンプレートで使用できる変数の一覧
http://themes.gohugo.io/ たくさんのOSSのテーマがまとまっている

12. 動作が早過ぎる

最後に。 むしろ良いことなんですが、最初にhugo new site bookshelfしたとき、レスポンスが早過ぎて失敗してるのかと思いました。 スリープ入れるようにPullRequestすると安心できるかもしれません。

という感じで、皆様幸せなHugoライフを!

*1:もちろん手動でトップページを作っても良いです。

*2:もちろん、themeを使わずに自前で全てデザインすることも可能です。

*3:themeによるのかな?

Static Site Generator (静的サイト・ジェネレータ)とは

Static Site Generator の Hugo を使ってみました。 Hugoについての記事を書こうと思ったのですが、その前に Static Site Generator (静的サイト・ジェネレータ)とは何かについて自分なりに整理していたら記事が長くなってしまったので、この記事に独立させてみました。


Static Site Generator (静的サイト・ジェネレータ)というのは、ウェブサイトを作るツールです。 GithubPagesでサポートされているJekyllが最も有名ですよね。 自分は、今までJekyllしか使ったことがありません。

さて、ウェブサイトを作るポピュラーなツールは何でしょうか。 すぐに思い付くツールとしてはWordPressがあります。 WordPressは、サイト内の更新コンテンツのデータをRDBで管理します。 そして、そのコンテンツ・データをPHPのプログラムが取り出して動的にHTMLを生成します。 更新コンテンツの入力方法としては、WordPressの管理画面上のエディタなどで入力するのが普通でしょう。

一方で、Static Site Generator は、更新コンテンツをファイルとして管理します。 更新コンテンツを記述したファイルは、サーバにアップロードする前にHTMLに変換する必要があります。 ウェブ・ブラウザからのリクエストに対しては、RDBのデータから動的にHTMLを生成してレスポンスするのではなく、事前に生成済みのHTMLファイルを静的にレスポンスします。

WordPressのような動的にHTMLを生成する方式の利点は、更新コンテンツの入力や、そのコンテンツの公開/削除などの全てのワークフローをウェブで完結することができるという点です。*1 FTPソフトでファイルをアップロードしたり、ローカルでビルドしたりといったような作業は基本的に発生しません。 これは、ITリテラシーの低い人にとってはとてもありがたいことです。 一方で、その仕組み自体はやや複雑です。アーキテクチャとしてRDBを必要とするし、内部でPHPのプロセスも動いています。 当然、カスタマイズやトラブルシュートにはPHPRDBの知識が必要になってくることがあります。

Static Site Generator の利点は、全てのコンテンツをファイルで管理することができるという点です。 PHPなどのプログラミング言語は登場しません。*2 構成と仕組みがとてもシンプルです。 Static Site Generator の多くは、更新コンテンツをマークダウンで書くことをサポートしています。 特にプログラマなどにとっては、自分の慣れたエディタで慣れたマークダウン形式で書けるというのは嬉しいことです。 一方で、サイト更新のワークフローはITリテラシーの低い人にはややハードルが高いかもしれません。 理由は、ビルド環境を整えなければいけないことと、コンテンツの差分管理をGitなどのSCMで行うからです。

Static Site Generator は現在ではたくさんの実装がOSSで提供されています。 それらのまとめとしてはTop Open-Source Static Site Generators - StaticGenが見やすいです。 一番スターが多いのはやはりJekyllで、その次が電子書籍の出版などでもよく使われているらしいGitBookです。 今回自分は、次点となっているJavascriptで実装されたHexoGolangで実装されたHugoを簡単に試してみて、最終的にHugoを採用しました。


Hugoについては、次の記事に続きます。

*1:一度セットアップしてしまえば、です。セットアップやメンテナンスには当然別のレベルのITリテラシーが必要です。

*2:サイトの運用上必要ないというだけで、ビルドはプログラムが処理しています。

Ad Network(アドネットワーク)とAd Exchange(アドエクスチェンジ)

しばらくインターネット広告業界を離れていたので、色々基本的な概念がおぼろげになってしまいました。 アドネットワークとアドエクスチェンジってどっちがどんなだっけ?というやつです。言葉感が似ているので混ざりやすいんじゃないでしょうか。

Ad Netework(アドネットワーク)

複数の小規模媒体を束ねて1つの媒体のように扱えるようにする、擬似巨大媒体
農家と農協に農協に例えてみます。

  1. 個人経営農家(小規模媒体)は、作った作物(広告枠)を食べてくれる人(出稿してくれる企業=広告主)に販売したい。しかし、彼らが自分で営業活動をしてお客さん(広告主)を見つけてきて作物(広告枠)を販売するとしたら、それは非常にコストがかかります。というか多くの個人経営農家(小規模媒体)には事実上それは不可能です。*1
  2. そのため、ほげほげ農業協同組合(アドネットワーク)が、彼らの作物(広告枠)を束ねて、まとめてたくさんのお客さんに売ってくれます。
  3. ほげほげ農協(アドネットワーク)は、組合費や売上に対する手数料を徴収し、自身の財源とします。

Ad Exchange(アドエクスチェンジ)

アドネットワークの数が増えてくると、複数のアドネットワークへの入稿などの、広告主側の管理コストが非常に大きくなってきます。 そこで、様々なアドネットワークに統一的かつ柔軟に入稿/配信できる仕組みを作ろうということになりました。 この仕組みや取引市場自体をアドエクスチェンジと呼びます。

アドネットワークとアドエクスチェンジの違い

そもそも、各用語が扱っているレイヤーが全然違います。アドネットワークというのは単なる(擬似)媒体であり、広告市場のプレイヤーの1つの分類なのに対して、 アドエクスチェンジとは、媒体でも、広告主でも、まして代理店でもないです。アドエクスチェンジとは、取引市場や取引形態自体を指す用語です。
アドネットワークは媒体の一種、アドエクスチェンジは取引市場・取引形態を指す言葉。これを覚えておけば、きっとごっちゃにならずに覚えておけるはず!

*1:地産地消が回るコミュニティが全く存在しないわけではないです。またインターネットの登場によって、農家の販売チャネルの事情はだいぶ変わってきている(変わっていく)と思われます。