0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

gulp + Nunjucks の環境構築や、変数の外部ファイル化、マクロについて

Last updated at Posted at 2022-03-27

Nunjucks を使う機会があったので重要だと思ったポイントをまとめます。
間違いがありましたらご指摘いただけると嬉しいです。

テンプレート構文などは他の方がまとめてくださってます。
テンプレートの継承、三項演算子についても書かれていて大変重要です。

gulp + Nunjucks の環境構築

gulp-nunjucks-render を使う記事が多いですが gulp-nunjucks のほうが最終更新日が新しいので、本記事では gulp-nunjucks を使います。

この記事で使用しているバージョンは下記の通りです。

package.json より抜粋
"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

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 // 共通パーツ
gulpfile.js
  .src(['./src/njk/**/*.njk', '!./src/njk/**/_*.njk'])

共通パーツは出力してほしくないので「!」を付けることで除外指定します。

サイト全体設定を別ファイルにして共通化する

サイト名やOGP画像など定数をまとめた javascript ファイルを作成します。
javascript にした理由は、json だと計算式や関数が使えない、先に定義した定数の使い回しができないなど不便があるからです。

_const.js に共通データを格納します。

_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 で読み込みます。

gulpfile.js
      // サイト全体設定を外部ファイルから読む
      .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 %} したファイル内で有効です。
親で定義した変数を子は見れますが、子で定義した変数を親が見ることはできません。

変数を別ファイルにまとめて読み込む

上で解説したサイト全体設定とは違い、特定のページでのみ使う変数を別のファイルにまとめる方法です。

_items.njk
{% set list = [
  {
    id: 'apple',
    name: 'りんご',
    price: '100円'
  },
  {
    id: 'orange',
    name: 'オレンジ',
    price: '110円'
  }
] %}

import する時に as xxx で空間(?)を指定します。

index.njk
{% import '_items.njk' as items %}

{% for item in items.list %}
{{ id }} - {{ name }} - {{ price }}
{% endfor %}
結果
apple - りんご - 100円
orange - オレンジ - 110円

文字列のエスケープ処理をキャンセルする

下記のような内容はエスケープ処理されます。

{% set title = 'STAFF & CAST' %}
{{ title }}
結果
STAFF &amp; CAST

もしエスケープ処理をさせたくなければ | safe を使います。

{{ title | safe }}
結果
STAFF & CAST

再利用可能なマクロを作る

複数箇所で使い回しつつ一部だけ違うものはマクロを使います。
引数にデフォルトを指定できます。

_macro.njk
{% macro input(type='text', name='', value='') %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
{% endmacro %}
index.njk
{# マクロを呼び出す #}
{% import '_macro.njk' as macro %}
{% macro.input(name='field1') %}
結果
<input type="text" name="field1" value="" />

import した macro 内では外の変数は見えない

macro を import する時で注意するのは外の変数が見えないことです。

_macro.njk
{% macro input(type='text', name='', value='') %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }} - {{ hash }}" />
{% endmacro %}
index.njk
{% 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="メッセージ - " />
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?