2015 05 31

テンプレートエンジンECTで静的htmlにlayout/partial導入

ectjs

dreamweaverのテンプレート機能みたいなものが欲しかった

かつてdreamweaverでテンプレート機能を使って、ヘッダー/フッターなどの共通部分を管理してましたが、他のエディタを使うようになってからは全ファイルに検索/置換で対応してました。
知らないだけで他に方法があるのかもしれないけど、非効率でうっかりな対応漏れページが出てしまったりといいことはなかったので、どうにかならないかなと思ってました。
(PHPでincludeとか、SSIとかあるといえばあるけど、自分の手元だけで済ませられないかなという希望がありました。)

middlemanなどのstatic site generatorを少し試してみたりもしたんだけど、チームで運用するには、学習コストが高いなと感じてました。
正直自分もちゃんと使えてなかったと思う。
でもそれは全部入りのツールを使うからで、そもそもcss(sass)を書くためにタスクランナー使ってるし、作業環境のローカルサーバーの立ち上げもbrowserSync使えばいいし、ってことで、結局テンプレート(layout)とパーシャルファイルの一括管理ができればいい。

で、それってテンプレートエンジンの役割、ということで、テンプレートエンジンを検討すれば良いということにようやくきづいたのが最近です。

テンプレートエンジンの選択

重視した点

テンプレートエンジン候補

一部テンプレートエンジンではないものもありますが。

jade

http://jade-lang.com/

slim

http://slim-lang.com/

jadeもslimも、htmlを簡潔にかけるというのはわかるけど、学習コスト、既存プロジェクトからの移行のコスト、というところで見送り。

EJS

http://www.embeddedjs.com/
html記法のまま使える。
partialの手段もある。
<% include head %>

ただ、node.js/expressでの使用の際に、express3以降、ejsからはテンプレートエンジンの役割がejs-localsとして独立したとのこと。
ejs-localsのほうは、あまりメンテナンスされていないようで、ちょっとこれからの継続に疑問というか、もうこれ以上の発展はないのかなと思ったりしたので、ひとまず見送り。
https://github.com/RandomEtc/ejs-locals

gulp-file-include

https://www.npmjs.com/package/gulp-file-include
partialファイルをincludeするというピンポイントなもの。
今の自分が探している条件にはあてはまるんだけど、そこまで人気があるかというとそこまでではなさそうなので、開発が継続されるかちょっと心配。

ect

http://ectjs.com/
コンパイル最速とうたっているよう。
EJSに近くhtml表記をそのまま使える。 テンプレートエンジンの中では後発でこの先の開発が継続されるのはある程度期待していいのかなと。
というわけで、ectを採用しました。

2015年2月頃にこの投稿の下書きを書いていて、上記のように判断しましたが、ect自体2014年6月から更新されてないようです。
この後にかいているgulpから使うgulp-ectに関しても2014年7月から動きがなく、download数もかなり少ない。
もしかしたらやっぱりEJSのほうが安心かなと思いつつ、とりあえず現状で自分はectで満足してます。

ectをgulpから使う

gulp-ect

https://github.com/AveVlad/gulp-ect
sassの調整などとあわせて、gulpから使いたかったので、こちらを検討。
ただどこみても、requireのところ
var ect = require('ect'); って書いてあるんですが、実際は
var ect = require('gulp-ect'); のはず。
というか、それじゃないとエラーが出てうまく動かなかった。
(エラーは以下の感じ)
TypeError: Object [object Object] has no method 'on'

ディレクトリ構造を保持してくれない

2015.02.24時点では、ディレクトリに入っているファイルも全部、展開先のルートに指定したところに展開されてしまうようで、同じ名前のファイルがある場合(index.ectと/hoge/index.ectとか)、エラーが出る。
というか、万が一同じ名前がなくてエラーが出てなくても展開してほしいディレクトリじゃなくて、展開先ルートにあるのでダメ。
調べながら調整してみた感じでは、展開先のディレクトリ名のところをちゃんとすればいけたんだけど、下記がマージされれば大丈夫っぽい。

あと、include、extendなどのパスがちゃんとあってないとエラーが出る。 動作確認だけと思って適当に書いてたら、エラー出た。

上記のindex.jsに差し替えた場合は、includeやextendの読み込みのパスは、現在のファイルからのパスではなく、 ルートディレクトリからのパス。 gulp.srcで "/htdocs/**/*.ect" を渡していた場合は、「/htdocs/」がルートになる。 /htdocs/と同階層にある/template/ディレクトリ内のheader.ectをincludeする場合は、以下のようになる。 <% include '../template/header.ect' %>

partials

http://ectjs.com/#partials <% include ‘ファイル名’ %>

<% include ‘ファイル名’, {プロパティ: ’値'} %>

という感じで値を渡すこともできる。

例えば、以下のように、渡したいパラメータをまとめて、includeの部分に渡す。 <% inc_param = { page: 'index', path: './' } %>

<% include '../template/header.ect', inc_param %>
<% if @page is 'index' : %> class="current"<% end %>

として、ナビゲーションのカレント表示を切り替えるとか。

パラメータはectファイルの最初にまとめて記載することで、変更が漏れにくく、わかりやすいのかなと。
middlemanのfrontmatterみたいな感じ。

extend

http://ectjs.com/#inheritance レイアウトファイルを用意して、コンテンツ部分を差し替える感じ。 個別ページファイルからのテンプレートファイルの呼び出しは下記。 <% extend '../template/layout.ect' %>

こちらは、パラメータを渡すことはできませんでした。

blocks

http://ectjs.com/#blocks ページ独自のcssやjsを別途読み込みたい時などのために、コンテンツ部分とは別に挿入領域を確保できる。

実際にテンプレートファイルとして使うには

制作するファイルが必ずしもドメインルートというわけではないと思うので、ナビゲーションやcss/jsなどの外部ファイルの読み込みのパスを相対にしたいと思っているんですが、このextendやstatic site generatorなどでは、
href="/index.html" のようにルート相対パスで書くからパス書き換える必要ないよねという感じです。
ですが自分は、クライアント確認用のテストサーバーに日付でディレクトリ切ることが多かったので、この必要性を特に感じてました。

extendにパラメータを渡せたらincludeと同じように使えたらいいのになと思うんですが、とりあえずかなり原始的になってしまうけれど、includeのようにパラメータを渡せる場合は、ルートへのパスをパラメータ内に持たせて href="<%- @PATH %>news/" みたいな感じで置き換えるようにやってみようかなと思います。

その他

エディタにatom使う場合は、language-ectというpackageを使うとシンタックスハイライトされます。
https://atom.io/packages/language-ect
上記ページに記載ありますが、sublime textもSublime-ECTというpackageがあるみたい。

今のところ

途中にもちらっと書きましたが、あまり更新されてないし、どうもイマイチ世間的にも注目されてないっぽいのが気になりますが、いくつかの制作で使ってみたけどなかなかいい感じ。
今までこういった手段を持っていなかった身としては、かなり救世主な感じ。
みなさんect使いましょう。