前回のポストの続きです。
gulp-changedを使って変更のあったテンプレートのみコンパイルする方法では、include
元のファイルに変更が合った場合に、include
先のpugファイルに変更が伝わらない問題がありました。
今回は、この問題を解決(回避)する方法を紹介します。
解決したい問題
一般的なGulpタスクのように、
- 1. ファイルの変更を検知
- 2.
src/**/*.pug
を全て再コンパイル - 3. browserSyncをリロード
のような流れでタスクを書くと…pugファイルが増えた時、2.のコンパイルに時間がかかり、リロードがなかなかされなくなります。
数秒〜数十秒にもなると開発どころではありません。。
pugのlayout
やinclude
といった機能を使っていると、「どのファイルがどのファイルをインクルードしているか」が分からないため、全てのファイルを再コンパイルする必要があり、この問題を解決する事がどうにも難しいようです。
そこで、コンパイルした静的なHTMLをホストするのではなく、PHPなどと同様に動的に、リクエストに対してHTMLを生成すれば良いのでは…?と思いmiddleware化する事でこれを実現しました。
コンパイルはbrowserSyncのmiddlewareを使う
browserSyncは内部的にconnectが採用されているので、同様のインタフェースでmiddlewareを定義できます。
middlewareを作る
やりたい事は、HTMLへのリクエストに対してpugのコンパイル結果を返すだけなので、1つ関数定義するだけで実現できました。
(gulp-dataなどでデータを渡している場合、もう一手間必要です。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function pugMiddleWare (req, res, next) { const requestPath = url.parse(req.url).pathname; // .html or / で終わるリクエストだけを対象とする if (!requestPath.match(/(\/|\.html)$/)) { return next(); } // HTMLファイルが存在すれば、HTMLを返す const htmlPath = path.parse(requestPath).ext == '' ? `{requestPath}index.html` : requestPath; if (fileExists(path.join('path/to/base/dir', htmlPath))) { console.info(`HTML発見 ${htmlPath}`); return next(); } // pug のファイルパスに変換 const pugPath = path.join('path/to/src', htmlPath.replace('.html', '.pug')); // pugファイルがなければ404を返す if (!fileExists(pugPath)) { console.info(`Pugファイル見つかりません ${pugPath}`); return next(); } // pugがファイルを見つけたのでコンパイルする const content = pug.renderFile(pugPath, { basedir: 'path/to/src, compileDebug: true, pretty: ' ', ...data }); // コンパイル結果をレスポンスに渡す res.end(new Buffer(content)); next(); } |
browserSyncにmiddlewareを渡す
あとは、このmiddlewareをbrowserSyncのmiddlewareとして渡してあげれば完了です。
1 2 3 4 5 6 7 |
browserSync.init({ server: { middleware: [ pugMiddleWare ] } }); |
gulp.watch()
コンパイルはリクエストを受けた時点で行うので、ファイルの変更を検知したらリロードするだけでOKです。 これで、コンパルの待ち時間は実質0秒になりました!
1 2 3 |
gulpWatch('path/to/src/**/*.pug', () => { browserSyn.reload() }) |
さいごに
この方法ならpugにかぎらず、どんなテンプレートエンジンでも同じ方法でコンパイルを最小限に抑えることができます。
ただあくまでも、browserSyncなどを使った開発時に有効な手段のため、最終書き出し時にはある程度時間がかかります。
libsassの様にpugが高速化される事を期待したいところです。