Jekyll Assets & Rails Assets から脱却する作業をはじめた話は先日書いたが、その後ちょくちょく作業を進めて、この土日 2 日間で Jekyll + npm + webpack という構成への移行を完了させた。インストールした node モジュールや npm scripts、webpack.config.js の内容などを知りたい方は、このサイトの GitHub リポジトリにある各ファイルを参照のこと。そっちには今回触れないので。
開発中は JavaScript で CSS を inject という形1だけど、build の時には JS ファイルから分離して、いままでと同様それぞれキャッシュ対策用のハッシュを付けたファイル名で出力するようにしている。内容に変更があればハッシュ値も変わるので当然ファイル名も変わる訳だが、問題はそれを Jekyll にどうやって伝えるかになる。
Jekyll Assets にはそれ専用の liquid タグが用意されていて、{% stylesheet style %}
とか書いておけばあとは自動でやってくれたが、そんな面倒を見てくれる仕組みはもうないので、自前でなんとかする必要がある。最初は liquid タグを追加するプラグイン書いて…とか思っていたが、よく考えたらそこまでしなくても Data Files を使う方法があった。
Data Files
Data Files は Jekyll に独自のテンプレート変数を追加する仕組みで、特定のディレクトリ(デフォルトでは _data)にファイルを置けば site.data.filename['key'] という形でそのファイルで定義された値を参照できる。当初は YAML 形式のファイルしか置けなかったと記憶しているが、いまでは CSV や JSON 形式のファイルも置けるようになっている。
JSON が置けるということは、いわゆるマニフェストファイル(manifest.json)をここに書き出せば、Jekyll のテンプレート変数でハッシュ付きファイルへのパスを参照できるという訳だ。あとは標準の liquid タグを使って、それぞれの環境に合わせた link 要素や script 要素が出力されるようにすればいい。
Let’s Try
マニフェストファイルを出力する webpack プラグインはいくつかある。今回は Webpack Assets Manifest を使ったけど、Webpack Manifest Plugin などでも別に構わない。もちろん設定は使うプラグインに合わせて書き換える必要があるが。
const AssetsManifest = require('webpack-assets-manifest');
// …
const buildConfig = {
// …
plugins: [
// …
new AssetsManifest({
output: path.resolve(__dirname, 'source', '_data', 'manifest.json'),
publicPath: publicPath
})
]
};
Jekyll の方では build の際に JEKYLL_ENV=production を付けると jekyll.environment に production がセットされるので、あとはこれを利用して条件分岐して、それぞれの環境に合わせて出力を変えるだけ。
JS ファイルは常に読み込まれる必要がある2ので、ファイルパスだけ変更すれば大丈夫。
<script src="{% if jekyll.environment == 'production' %}{{ site.data.manifest['main.js'] }}{% else %}/assets/main.js{% endif %}"></script>
CSS ファイルは前述のように build の時しか出力されないので、次のようにしておく。実際に出力されるファイル名(style.css)ではなく、エントリーポイントに基づくキーを指定する必要があることに注意。ちなみに、今回のようにエントリーポイントがひとつだけの場合のデフォルトは main になるようだ。
{% if jekyll.environment == 'production' %}
<link rel="stylesheet" href="{{ site.data.manifest['main.css'] }}" media="all" />
{% endif %}
あと気をつけないといけないのは、当然ながら最新の manifest.json が参照されないと意味がないので、かならず webpack によるアセットの build が完了したあとに Jekyll の build が走るようにすることくらいだろうか。その際、先日書いたように keep_files にアセットの出力先を指定しておくのも忘れずに。
そんな訳で、とりあえず今年の懸案事項がひとつ片づいた。この構成だと CSS を書いてる最中には不必要なページの build が走ることはないので、HMR や LibSass の速度などともあいまって、かなり快適に開発ができそうな印象。無駄に CSS に手を入れてしまいそうで怖い。
逆も同様ではあるのだが、Jekyll の速度がアレなので、ブログ書きとかはそれほどはかどる訳ではない。v3 にすれば改善されるのだろうか…まあ、こっちはそのうち。
Jekyll の build なども全部 npm scripts にまとめてしまったので、不要になった Foreman と Procfile も削除した。Gemfile がスカスカになった。