[Grunt & Yeoman] grunt-simple-ejs テンプレートを使って HTML を生成する

head や aside、nav などの共通要素をはめ込んで、数十ページのスタティックなHTMLを作成したく、テンプレートエンジンを調べたところ、grunt-simple-ejs を見つけたので使ってみました。

Node.js や Grunt まわりだけでも、いろいろな技術がたくさんあって、アウトラインもまだつかめていないです。

こちらのエントリーが勉強になりました。

タイトルの件については、Qiita で下記の解説付きエントリを見つけ、目的を果たせそうなので、動かしてみました。

Contents

ejs

素の ejs はどんなものか。

zend や rails でみた <%= %> のような記法で埋め込むようで、学習コストが低そう。

インストール

% npm install --save-dev grunt-simple-ejs

Gruntfile

少し仕様が変わっていました。

  • foo.html.ejs が template ファイル。
  • Gruntfile 内で指定した options がテンプレートに挿入される。
  • foo.html が生成される。

Gruntfile.coffee

'use strict'
module.exports = (grunt) ->
  # プラグインの読み込み
  grunt.loadNpmTasks 'grunt-simple-ejs'
  # グラントタスクの設定
  grunt.initConfig
    # config
    dir:
      src: 'src'
      dest: 'dist'
    pkg: grunt.file.readJSON "package.json"
    # grunt-simple-ejs
    ejs:
      dev:
        templateRoot: '<%= dir.src %>/template'
        template:     '*.ejs'
        dest:         '<%= dir.dest %>'
        options:
          title: 'タイトル'
          description: 'サイトの説明です。'
  # タスクコマンドの設定
  grunt.registerTask 'default', ['ejs:dev']

つかいかた

% grunt ejs:dev
Running "ejs:dev" (ejs) task
[write] dist/index.html
Done, without errors.

src/template/index.html.ejs

<html>
<head>
<title><%= title %></title>
<meta name="description" content="<%= description %>" />
</head>
<body>
<h1><%= title %></h1>
<p><%= description %></p>
</body>
</html>

dist/index.html

<html>
<head>
<title>タイトル</title>
<meta name="description" content="サイトの説明です。" />
</head>
<body>
<h1>タイトル</h1>
<p>サイトの説明です。</p>
</body>
</html>

以上が基本的な使い方。

options を別ファイルで設定する

2014-01-04_sejs_02

Gruntfile.coffee

該当箇所を下記のように変更する。

options: '<%= dir.src %>/template/options.json'

src/template/options.json

ページ毎に異なる要素を json で管理する想定。
home と news を設定してみる。

{
  "home": {
    "title": "home",
    "description": "サイトの説明です。"
    },
  "news": {
    "title": "news",
    "description": "newsの説明です。"
  }
}

src/template/index.html.ejs

<!doctype html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title><%= home.title %></title>
  <meta name="description" content="<%= home.description %>" />
</head>
<body>
  <h1><%= home.title %></h1>
  <p><%= home.description %></p>
</body>
</html>

template を分割して、include する

2014-01-04_sejs_01

head.ejs という読み込むテンプレートを用意します。

src/template
├── index.html.ejs
├── news
│   └── news.html.ejs
├── options.json
└── partials
    └── head.ejs

下位ページの作成テストとして、あわせて news.html.ejs を追加します。

src/template/index.html.ejs

partials までの path は、index.html.ejs からの相対パスとして扱われるよう。

<!doctype html>
<html lang="ja">
<head>
<% include /partials/head %>
  <title><%= home.title %></title>
  <meta name="description" content="<%= home.description %>" />
</head>
<body>
  <h1><%= home.title %></h1>
  <p><%= home.description %></p>
</body>
</html>

src/template/news/news.html.ejs

<!doctype html>
<html lang="ja">
<head>
<% include ../partials/head %>
  <title><%= news.title %></title>
  <meta name="description" content="<%= news.description %>" />
</head>
<body>
  <h1><%= news.title %></h1>
  <p><%= news.description %></p>
</body>
</html>

src/template/head.ejs

  <meta charset="UTF-8">

Gruntfile.coffee

/news ディレクトリ以下のテンプレートを対象に加えます。

template:     ['*.ejs', 'news/*.ejs']

partials は不要でした。

分からない点

組み立て方が分からなかったもの。

  • options で渡せる env: 'dev' 環境変数の使い方。
  • 上記の分割テンプレートと options ファイルを利用した場合に、head.ejs に options.json を読み込み、呼ばれた .html.ejs に応じて、該当する json を返す。
  • layout ファイルを用意、content 部を複数ファイル記述して、layout ファイルにはめ込み html 生成。extend。

補遺

その他のテンプレートエンジン。ちょっと拾っただけでも色々ある。

Jade

Handlebars

ECT