gulpとjsonとpugでhtml量産
普段静的サイトを構築する際に、gulpでpugをコンパイルして作っています。
それを拡張して、jsonからデータをとってきてpugで作ったテンプレを利用してページの量産ができる構築環境を作りました。
devDependencies
多いな……! というわけでyarn addするならこんな感じ。
yarn add -D fs-extra gulp gulp-pug gulp-rename
私はgulpfileにおいてimportが必要なのでgulpfile.babel.jsを使っていますが、この記事を書くにあたりgulpのドキュメントを改めて読んだらgulpfile.esm.jsでもいいのではという気もします。
まあとにかく今インストールしたものをgulpfileでimportします。
gulpfile.babel.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import fs from 'fs-extra'; import gulp from 'gulp'; import data from 'gulp-data'; import pug from 'gulp-pug'; import rename from 'gulp-rename'; const buildTemplate = () => gulp.src('src/data.json') .pipe(data((file) => { const filepath = file.path.replace(file.base, '').replace(/\\/g, '/'); // jsonのパス const json = JSON.parse(fs.readFileSync(`./src${filepath}`, 'utf8')); // jsonの中身を取得 for (const key of json) { gulp.src('src/template.pug') .pipe(data(() => ({ $setting: key.setting, // jsonの中身により変わる部分 $content: key.content }))) .pipe(pug, {basedir: 'src'}) .pipe(rename(`${key.setting.id}.html`)) // jsonで設定したidをもとにファイル名を指定する .pipe(gulp.dest('htdocs')) } })); |
jsonのデータの中身分forを回して、テンプレートに変数を渡し、それをコンパイルする。という流れになります。
下記は複数ディレクトリで量産したいとき。デザインが違う想定で、data.jsonは同階層にある_template.pugを参照するように設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// import 省略 const buildTemplate = () => gulp.src('src/**/*.json') .pipe(data((file) => { const filepath = file.path.replace(file.base, '').replace(/\\/g, '/'); // jsonをワイルドカードで拾っているのでファイルパスを取得 const jsonpath = `./src${filepath}`; const templateFile = jsonpath.replace('data.json', '_template.pug'); // jsonのパスから同階層にある_template.pugを見つける const relative = filepath.replace('data.json', ''); // 階層の深さを取得 const json = JSON.parse(fs.readFileSync(jsonpath, 'utf8')); // jsonの中身を取得 for (const key of json) { gulp.src(templateFile) .pipe(data(() => ({ $setting: key.setting, // jsonの中身により変わる部分 $content: key.content }))) .pipe(pug, {basedir: 'src'}) .pipe(rename(`${relative}${key.setting.id}.html`)) // jsonで設定したidをもとにファイル名を指定する .pipe(gulp.dest('htdocs')) } })); |
json
jsonのオブジェクトの最上位階層のキーはgulpfileに合わせる必要があります。上記のgulpfileの場合はsettingとcontentです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[ { "setting": { "id": "test", "path": "./" }, "content": { // 中身は自由。階層が深くなってもpugで拾いきれるなら問題なし }, "test": {}, // この階層を増やす場合はgulpfileでも増やす }, { "setting": { "id": "dir/underlayer", "path": "./../" }, "content": {} } ] |
4行目で指定しているidによりtest.htmlが、14行目に指定しているidでtest.htmlと同階層にdirというディレクトリができ、その下層ページとしてunderlayer.htmlができます。
同じテンプレを使うなら、ディレクトリを複数作らなくてもid次第で階層を深くすることができます。ただし階層が変わると相対パスがめちゃくちゃになるので、相対パスを使いたかったら5,15行目のように相対パス用の値を渡してあげる……というようなことが必要になります。
pug
テンプレは、条件分岐やループを駆使して変数を読み込むだけでいいように作る必要があります。
gulpfileで渡している$settingと$contentというオブジェクトを使い倒します。
まとめ
gulp+pug+jsonで工夫次第で爆速構築できます!sandboxで見せたかったけど断念。