読者です 読者をやめる 読者になる 読者になる

望月いちろうのREADME.md

書き溜めておいた技術記事や旅行記のバックアップです。

ect | Node.jsの高速テンプレートエンジン

Node.js

f:id:mochizuki_p:20170111165510p:plain

Webアプリケーション開発の生産性を飛躍的に上昇させ、もはや必要不可欠とも言えるテンプレートエンジンです

その中でも、今回はその速さに定評のあるectを紹介しようと思います。

Expressでの利用を前提に説明します。

公式

github.com

特徴

まずはその特徴について

  • 高速性
  • テンプレートのキャッシュに対応
  • テンプレートの変更に応じて差分を取る
  • CoffeeScriptの文法
  • 複数行にも対応
  • Atomでのハイライトにも対応

高速性

ectはejsやjadeなどのNode.jsでよく用いられるテンプレートエンジンに比べ、非常に高速に動作します。

キャッシュに対応

これはテンプレートを利用するたびに毎回ROMから読み込むことなく、メモリに載せておきます。

こうすることで非常に高速に動作するのですね

CoffeeScript

ectは基本的にCoffeeScriptの文法を採用しています。これはJavaScriptをより簡潔に書くために考案された言語です。

今ではその利用は下火になっていますが、その設計思想はES2015,ES2016などのJavaScriptの最新規格に大きな影響を与えたとされています。

JavaScriptが書ける人であれば、ほぼゼロの学習コストで習得できるでしょう。

Atomでのハイライトにも対応

GitHub特製のテキストエディタであるAtomでは

ectのハイライト用プラグインが利用可能です。

基本的な使い方

導入

Expressアプリケーションのホームディレクトリで

sudo npm install ect

とすればOKです。

Expressで利用する

Expressでのデフォルトのテンプレートエンジンはjadeまたはejsになっています。

これをectに変更してみましょう.

変更するのは以下の箇所です。

// view engine setup

app.set('views', path.join(__dirname, 'views'));

app.set('view engine', 'ejs');

ここを以下のように書き換えます。

var ECT = require('ect');
var ectRenderer = ECT({ watch: true, root: __dirname + '/views', ext : '.ect' });

app.set('view engine', 'ect');
app.engine('ect', ectRenderer.render);

これでテンプレートエンジンがejsからectに切り替わりました。

ついでに/views内のテンプレートもすべて、拡張子をectに変更しておきましょう。

テンプレートの利用

特定のパスに対して、テンプレートhogeを利用するには以下の形式で指定します。

router.get("/hoge",(req,res,next)=>{

   return res.render("hoge",{title:"Hello ect"});
});

大事なのがrender()メソッドです。ここでは、第一引数でテンプレートを指定して、第二引数(オブジェクト)で値をテンプレートに渡します。

ご存知でしょうがExpressでテンプレートを配置するのは/viewsフォルダです。ここにhoge.ectを配置します。

touch hoge.ect

これを以下のように編集してみましょう。

<!DOCTYPE html>
<html>

    <head>
        <title> <%- @title %> </title>
    </head>
    
    <body>
             <h1> <%- @title %> </h1>
    </body>

</html>

そして保存して、ホームディレクトリに移動、そしてExpressを起動してください。

そしてGET /hogeにアクセス

http://localhost:3000/hoge

すると

<!DOCTYPE html>
<html>

    <head>
        <title> Hello ect </title>
    </head>
    
    <body>
             <h1> Hello ect </h1>
    </body>

</html>

となりました。

つまり、hoge.ectで<%- @title %>となっていた部分が

render()で渡した値に置き換わっているわけですね。

出力

エスケープなし

 <%- @title %> 

エスケープあり

なしの場合に比べて余分に時間がかかります。

 <%= @title %> 

if文

特定の変数が存在する時にだけ、特定のテンプレートを出力することもできます。

<% if @flag : %>
    <h2>フラッグが立っている</h2>
<% end %>

この場合はflagに任意の値が設定されているときに

フラッグ

展開されます。

以下のようにif ~ else文にすることも可能です。

<% if @flag : %>
    <h2>フラッグが立っている</h2>
<% else : %>
    <h2>フラッグなし</h2>
<% end %>

この場合はflagに任意の値が設定されているときに

<h2>フラッグ</h2>

展開され、

<h2>フラッグなし</h2>

は展開されません。

for文

テンプレートエンジンを利用する一番の利点はfor文を利用して同じ構造でそれぞれ違う値をもった要素を複数配置できることです。

たとえば、以下のような同じ構造をもったオブジェクトの配列に対して

languages = [
  {"name":"Python","developer":"Guido van Rossum"},
  {"name":"Ruby","developer":"Matsumoto Yukihiro"},
  {"name":"Java", "James Gosling"},
  {"name":"C++","Bjarne Stroustrap"}
]

以下のようにテーブルの列を中身だけ変更して並べることができます。

<table>
  <tr>
     <th>言語名</th>
     <th>開発者</th>
  </tr>
  <% for language in @languages : %>
     <tr>
         <td><%- language.name %></th>
         <td><%- language.developer %></th>
     </tr>
  <% end %>
</table>

子要素

テンプレート内に任意のほかのテンプレートを展開することも可能です

<% include "child" %>
<p>子要素です</p>

結果

<div>
<p>子要素です</p>
</div>

基本的に変数はそのまま利用できる

<p><%- @title %></p>
<!DOCTYPE html>
<html>

    <head>
        <title> <%- @title %> </title>
    </head>
    
    <body>
           <% include "child" %>
    </body>

</html>

変数を再定義して渡すこともできる。

<!DOCTYPE html>
<html>

    <head>
        <title> <%- @title %> </title>
    </head>
    
    <body>
           <% include "child", {title: @title + "なんちゃって"} %>
    </body>

</html>



ブロック

<%- row = (language) %>
     <tr>
         <td><%- language.name %></th>
         <td><%- language.developer %></th>
     </tr>
<% end %>


<table>
  <tr>
     <th>言語名</th>
     <th>開発者</th>
  </tr>
  <% for language in @languages : %>
     <%- row language %>
  <% end %>
</table>

継承

親要素を定義して子要素からそれを呼び出すこともできます。

<% extend 'parent' %>
<div>Expressではこちらを指定します。</div>
<html>
   <head>
      <meta charset="uft-8"/>
   </head>
   <body>
       <% content %>
   </body>
</html>

子要素をExpressから呼び出すと、その内容が親要素の<% content %>として出力されます。

結果

<html>
   <head>
      <meta charset="uft-8"/>
   </head>
   <body>
       <div>Expressではこちらを指定します。</div>
   </body>
</html>