Hugoの設定ファイルを分割しfswatchを使って結合してみる
Nプログラマ(@Nprog128)です。
今回は、Hugoの設定ファイルconfig.tomlを分割・結合するという内容です。
config.tomlの分割は 公式でサポート (params, languages, menusなど)されていますが、任意のパラメータの場合はこれができないようです。
一つの設定ファイルにモリモリ書いてもいいのですが、1000行を超えてくると編集がツラくなってきます。
そこでfswatchを使ってファイル監視を行い、編集を検知したらconfig.tomlに結合するようにしてみました。
ファイル単位で分割しているため、設定の場所や編集のしやすがラクになるかもしれません。
この記事の内容を使い続けてみて実感したことですが、この方法ではHugoのライブプレビューのビルドが若干遅くなるような気がします(あくまで体感です)
configにモリモリと書くよりは、data templateを使った方がいいと思います。
環境
- Mac OS X High Sierra 10.13.6
- fswatch 1.14.0
準備
まずは検証のため空のプロジェクトを作成します。
1\$ hugo new site sample
sampleディレクトリの階層構造はこうなっています。
1./
2├── archetypes
3│ └── default.md
4├── config.toml
5├── content
6├── data
7├── layouts
8├── static
9└── themes
HugoのConfiguration Directory を参考にconfigディレクトリを作成します。 その下に_defaultディレクトリを作成して、config.tomlをそこに移動させます。
変更した結果、以下のようなディレクトリ階層になりました。
1./
2├── archetypes
3│ └── default.md
4├── config
5│ └── _default
6│ └── config.toml
7├── content
8├── data
9├── layouts
10├── static
11└── themes
これで準備完了です。
設定ファイルを分割していく
分割ファイル用のディレクトリを作成
先に分割したファイルを配置するためのディレクトリを作成します。 ディレクトリ名は任意なのでtmpという名前にしました。 このディレクトリがfswatchの監視対象になります。
またこのディレクトリはhugoのサーバ起動時のビルド対象にならないので、必要以上にビルドがされないのもいいところかなと思っています。
(おそらくConfiguration Directoryのルールから外れているため、ビルドされないのだろうと思っています)
ファイルの分割
ここからは先程移動させたconfig.tomlを分割していきます。
分割前の内容はこんな感じです。
config.toml コードを開く
これらを4つのファイルに分割してみます。
- 00.base.toml
- myparams-hoge.toml
- myparams-fuga.toml
- myparams-piyo.toml
分割したファイルを先程作成したtmpディレクトリに配置します。
1./
2├── _default
3│ └── config.toml
4└── tmp
5 ├── 00.base.toml
6 ├── myparams-fuga.toml
7 ├── myparams-hoge.toml
8 └── myparams-piyo.toml
baseだけ数字がついているのは、結合時にソートしてconfig.tomlで一番上に記述したいからです。
config.tomlはfswatchの検知により常に自動生成されるため、削除しなくても問題ありません。
この仕組みを導入するとconfig.tomlは常に分割したファイルを結合した結果の上書き更新になります。
導入する前にはバックアップを取るようにお願いします。
またconfig.tomlを編集する場合は、必ず分割ファイルを編集するようにしてください。
分割したファイルのコード
00.base.toml コードを開く
myparams-hoge.toml コードを開く
myparams-fuga.toml コードを開く
myparams-piyo.toml コードを開く
ファイルの監視・結合
ファイルの分割ができたので、次はfswatch(
公式サイト
)を使った監視をします。
コマンドがない場合はbrewコマンドでインストールします。
1brew install fswatch
ファイル変更を検知したらconfig.tomlに結合する処理が必要なので、そのシェルスクリプトを作成しました。
update-config.sh コードを開く
スクリプト内で一時ファイルの作成と削除について、こちらのサイト様の記事を参考にしました。
ありがとうございます。
使い方
作成したスクリプトをhugoで作ったディレクトリと同じ階層に配置します。
1./
2├── sample
3└── update-config.sh
この状態でfswatchコマンドを実行します。
1fswatch -xr ./sample/config/tmp | xargs -I{} ./update-config.sh {}
オプションの-rをつけることで、分割した設定ファイルが入ったtmpを再帰的に監視します。
また-xをつけることでどのようなイベントなのかが表示されるようになります。(これを使ってスクリプト内で条件判定をしています)
ファイルの変更を検知したら、その情報をupdate-config.shに渡します。
渡された内容はupdate-config.shの$1に入ってきます。
後述しますが、1ファイルの変更で複数の通知がくるのでスクリプト側で1回だけの処理になるようにしています。
スクリプト内でファイルパスを指定している部分があるので、そこを書き換えれば任意の場所に配置することができます。
コードの説明
(1) 一時ファイルについて
mktemp
を使うと一時ファイルの生成し、削除し忘れても一定期間立つと自動的に削除もされるみたいです。これは便利で勉強になりました。
(2) 1ファイルに対して1度だけ処理について
fswatchでファイル更新をするとその通知内容が飛んでくるのですが、編集に使用したツールによって通知内容が異なるみたいです。ツール名 | 通知の内容 |
---|---|
PHPStorm | 1ファイルにつき3つの通知 |
Vim v8.1 | 1ファイルにつき2つの通知 |
自分はPHPStormを使っていたので、fswatchからの通知内容はこんな感じでした。
1変更したファイルパス___jb_tmp___ Created Renamed Updated IsFile}
2変更したファイルパス Renamed OwnerModified IsFile}
3変更したファイルパス___jb_old___ Removed Renamed IsFile}
一番最後の通知に対して一度だけ分割ファイルの結合処理をするようにしました。
他のツールの場合はfswatchの実行画面で通知内容を確認して、条件分岐内のRemovedのところを変更すればうまく動作すると思います。
(3) 分割ファイルの結合処理
ここがメインの処理です。
findコマンドでtmpディレクトリ内のファイル一覧を取得します。
1find ./sample/config/tmp -type f
設定ファイルの中身は、昇順ソートのファイル単位で記述したいのでソートします。
findで出力したファイル一覧はソートされていないので、パイプで出力をsortに渡してソートします。
1sort
xargsコマンドを使い、ソートされたファイル一覧を一つずつcatで出力したものを一時ファイルの変数へ書き込んでいきます。
出力結果を追記していきたいので>>
を使っています。
1xargs -I{} cat {} >> $tmpfile
これが終わるとtmpディレクトリ内のファイルの内容全てが、一時ファイルの変数へ書き込まれます。
(4) 一時ファイルからconfig.tomlへ書き出し
先程の一時ファイルの内容をconfig.tomlへ上書きします。hugo serve
で起動している場合は、ここでconfig.tomlが更新されたのでページのリロード処理が走ります。
使ってみる
先程作ったスクリプトを使ってみます。
sampleとupdate-config.shを配置してあるディレクトリに移動後、使い方で書いたコマンドを実行します。
1fswatch -xr ./sample/config/tmp | xargs -I{} ./update-config.sh {}
これで実行中になるので別のterminalを起動させて、myparams-hoge.tomlを編集します。
次のように変更して保存します。
変更前 コードを開く
変更後 コードを開く
保存した後、結合されて作成された./sample/config/_default/config.tomlの中身を確認すると、myparams-hoge.tomlの変更が反映されていることが確認できました。
config.toml コードを開く
00.base.tomlなど他のファイルを変更しても同じように変更内容が反映されます。
おわりに
今回は、Hugoの設定ファイル(config.toml)を分割・結合するという内容でした。
ちょっと準備が大変でしたがこれを導入してみたら、かなり設定ファイルがスッキリとしました。
設定ファイルが肥大化してきたらお試しください。
それでは、このへんで。
バイナリー!