Nunjucks を使う機会があったので重要だと思ったポイントをまとめます。
間違いがありましたらご指摘いただけると嬉しいです。
テンプレート構文などは他の方がまとめてくださってます。
テンプレートの継承、三項演算子についても書かれていて大変重要です。
gulp + Nunjucks の環境構築
gulp-nunjucks-render
を使う記事が多いですが gulp-nunjucks
のほうが最終更新日が新しいので、本記事では gulp-nunjucks
を使います。
この記事で使用しているバージョンは下記の通りです。
"gulp-html-beautify": "^1.0.1",
"gulp-htmlhint": "^4.0.1",
"gulp-nunjucks": "^5.1.0",
"gulp-data": "^1.3.1",
インストール
gulp
はすでに動いている前提です。
yarn add --dev gulp-html-beautify gulp-htmlhint gulp-nunjucks gulp-data
gulpfile.js
const gulp = require('gulp');
const plumber = require('plumber');
const nunjucks = require('gulp-nunjucks');
const beautify = require('gulp-html-beautify');
const htmlhint = require('gulp-htmlhint');
const data = require('gulp-data');
module.exports = () => {
return (
gulp
// 「_」で始まるファイルは変換対象外
.src(['./src/njk/**/*.njk', '!./src/njk/**/_*.njk'])
// エラーで止まらないようにする
.pipe(plumber())
// サイト全体設定を外部ファイルから読む
.pipe(
data(() => {
return require('./src/njk/_const.js');
}),
)
// Nunjucks で変換
.pipe(nunjucks.compile())
// HTML整形
.pipe(beautify({ indent_with_tabs: false }))
// HTML構文チェック
.pipe(htmlhint('.htmlhintrc'))
// HTML構文チェックの結果を表示
.pipe(htmlhint.failReporter())
.pipe(gulp.dest('./dist/'))
);
};
gulpfile.js の解説
共通パーツをファイル出力対象外にする
下記のように共通パーツはファイル名を「_」
から始めると分かりやすいのでオススメです。
index.njk // index.html を出力する
about.njk // about.html を出力する
_header.njk // 共通パーツ
.src(['./src/njk/**/*.njk', '!./src/njk/**/_*.njk'])
共通パーツは出力してほしくないので「!」
を付けることで除外指定します。
サイト全体設定を別ファイルにして共通化する
サイト名やOGP画像など定数をまとめた javascript ファイルを作成します。
javascript にした理由は、json だと計算式や関数が使えない、先に定義した定数の使い回しができないなど不便があるからです。
_const.js
に共通データを格納します。
// jsやcssのキャッシュ対策に使う文字
const VERSION = Math.floor(Math.random() * 1000000);
const SITE_OGP_BASE_URL = 'https://example.com';
const SITE_OGP_IMAGE_URL = SITE_OGP_BASE_URL + '/img/ogp.jpg';
const SITE_TITLE = 'サイト名';
// 中略
// 書き出し用にまとめる
module.exports = {
VERSION,
SITE_OGP_BASE_URL,
SITE_OGP_IMAGE_URL,
SITE_TITLE,
// 中略
};
gulp-data
で読み込みます。
// サイト全体設定を外部ファイルから読む
.pipe(
data(() => {
return require('./src/njk/_const.js');
}),
)
グローバル変数として使えます。
<title>{{ SITE_TITLE }}</title>
変数、配列、連想配列
変数
{% set var1 = '内容' %}
変数表示 {{ var1 }}
変数表示 内容
配列
配列の最後に「,」を付るとエラーになります。
{% set array1 = [
'A',
'B',
'C'
] %}
配列表示 {{ array1[1] }}
配列表示 B
連想配列
連想配列も最後に「,」を付るとエラーになります。
{% set dic1 = {
yamada: {
name: '山田',
age: 20
},
suzuki: {
name: '鈴木',
age: 21
}
} %}
連想配列表示 {{ dic1.yamada.age }}
連想配列表示 {{ dic1['suzuki']['name'] }}
連想配列表示 20
連想配列表示 鈴木
Nunjucks の変数スコープ
変数は {% set foo = 'bar' %}
のように定義します。
変数のスコープは定義したファイルおよび、{% include %}
したファイル内で有効です。
親で定義した変数を子は見れますが、子で定義した変数を親が見ることはできません。
変数を別ファイルにまとめて読み込む
上で解説したサイト全体設定とは違い、特定のページでのみ使う変数を別のファイルにまとめる方法です。
{% set list = [
{
id: 'apple',
name: 'りんご',
price: '100円'
},
{
id: 'orange',
name: 'オレンジ',
price: '110円'
}
] %}
import
する時に as xxx
で空間(?)を指定します。
{% import '_items.njk' as items %}
{% for item in items.list %}
{{ id }} - {{ name }} - {{ price }}
{% endfor %}
apple - りんご - 100円
orange - オレンジ - 110円
文字列のエスケープ処理をキャンセルする
下記のような内容はエスケープ処理されます。
{% set title = 'STAFF & CAST' %}
{{ title }}
STAFF & CAST
もしエスケープ処理をさせたくなければ | safe
を使います。
{{ title | safe }}
STAFF & CAST
再利用可能なマクロを作る
複数箇所で使い回しつつ一部だけ違うものはマクロを使います。
引数にデフォルトを指定できます。
{% macro input(type='text', name='', value='') %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
{% endmacro %}
{# マクロを呼び出す #}
{% import '_macro.njk' as macro %}
{% macro.input(name='field1') %}
<input type="text" name="field1" value="" />
import した macro 内では外の変数は見えない
macro を import する時で注意するのは外の変数が見えないことです。
{% macro input(type='text', name='', value='') %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }} - {{ hash }}" />
{% endmacro %}
{% set hash = '#ハッシュタグ' %}
{% import '_macro.njk' as macro %}
{% macro.input(name='field1', value='メッセージ') %}
期待する結果。
<input type="text" name="field1" value="メッセージ - #ハッシュタグ" />
実際の結果はマクロの外側で定義した変数 hash
が反映されません。
<input type="text" name="field1" value="メッセージ - " />