テンプレートエンジンでHTMLを管理しよう。EJSのススメ

ページ数が多いサイト制作、地味に面倒なのがヘッダーやフッター等共通パーツの編集作業

WordPressやPHPを使えれば共通パーツのファイルを別に用意できるので問題ないけど、「HTMLファイルで制作」っていう案件、割とよくある。

「フッターの一部だけ修正」といった作業でも、一括置換を使えない様な内容だと何十ファイルも編集することになり疲弊してしまうので、なんらかの仕組み化は必須だ。

JSで共通パーツ用のファイルを読み込む方法やエディタソフトで管理するやり方とかもあるけど、今回はテンプレートエンジンのEJSというものを使用して管理する方法について書いていく。

普段コマンドライン(ターミナルとかコマンドプロンプトとか)を操作しない人にはハードルが高く感じてしまう部分もある。

ただ、とにかく使ってみて見えてくるものもあるので、当時疑問に感じたポイントなども交えつつ、上記技術の初学者でもとにかく手順通りに進めればEJSを使用可能になるエントリーになれば幸い。

このエントリーが役立ちそうな人

  • HTMLやCSSは問題なくかける
  • 複数ページサイト制作時、共通パーツの管理をシンプルにしたい
  • node.jsやタスクランナー、コマンドラインに馴染みがない

EJSとは

HTMLの記述をパーツ化できる技術。くらいの認識で大丈夫。

サイト共通で使用するパーツや文章を、1箇所の記述で使いまわしたりできるようになる。

SASSのHTML版みたいなイメージかな。

詳しい流れば後述するけど、導入までの手順がわかりにくいのが一番大きな壁かと思う。

コマンドラインnode.jsgulpをインストールするだけでも様々な方法があって、どれが正解かわからなくて混乱したり。。

でも逆にいえば、導入さえできてしまえば比較的低い学習コストでファイル管理が大幅に楽になる。

HTMLテンプレートエンジンという技術。

HTMLテンプレートエンジンのメリットデメリット

共通パーツを管理する方法という点において、JSで共通パーツ読み込みやエディタソフトでの管理とテンプレートエンジンを比較すると、メリットは

  • 出来上がるファイルは普通のHTMLファイル
    →JSだとJavascriptをオフにしているユーザーには共通パーツが見えなくなっちゃうし、読み込みまで時間がかかってしまったりする。
  • エディタソフトに依存しない
    →複数人で共同作業する場合でも、全員が使用ソフトを揃える必要がない。
  • 計算式やif・for・while文等のプログラミング文が使える
    →ページごとに処理を変えたり、大量の繰り返しを一行で書けたりする。

等があり、デメリットは

  • 導入までが多少手間
  • 複数人が関わる案件で、テンプレートエンジンの使用を知らない人が出力後のHTMLの方を編集してしまったりすると少しめんどい。

等がある。

参考記事

テンプレートエンジンの種類と比較

おそらくEJSが使用候補に上がる人は、他のテンプレートエンジンと比較検討している段階かもしれない。

そんなわけでHTMLテンプレートエンジンの比較をざっくりと。

といっても主流はEJSかPugになっている模様。

「HTMLテンプレートエンジン」とかで検索かけると大体、EJS、Pug、Edgeの記事がヒットする。

他のもざっくりみたけど大きな優位性を感じなかったので、上位三位までと言うことで紹介する。

EJS

<%
  let rootPath = '../';
%>
 
<%- include(rootPath + '_head') %>
<%- include(rootPath + '_header') %>
  <section>
    <h2 class="">タイトル</h2>
  </section>
<%- include(rootPath + '_footer') %>

記述例はこんな感じ。

通常のHTMLタグにEJS用の記述を含めることができる。どことなくPHPライクな印象。

外部ファイルをインクルードしたり、変数を設定する等、EJS用の記述をするときは<% 〜%>を使用する。

Pug

//- headerをインクルード
include _include/_header
main
  article
    header.header
      h1.title
        img(src="" alt="")

    section.home-About
      .home-About_Title

記述例はこんな感じ。

EJSに比べて随分個性的。いかに記述を減らすかに重点をおいている様に感じられる。

インデントでタグの階層を操作する。

少ない記述で済む。閉じタグが不要等のメリットがあり、記法を覚える学習コストの高さがデメリットか。

Edge

レイアウト用とコンテンツように分けて記述する

<!--レイアウト用-->
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ページタイトル</title>
</head>
<body>
  @include('header')
  <main>
    @!section('content')
  </main>
  @include('footer')
</body>
</html>
<!--コンテンツ用-->
@layout('layout.edge')
@section('content')
  <h1>ページタイトル</h1>
@endsection

記述例はこんな感じ。

ちょっとややこしく感じてしまうけど、記述の重複を減らせるみたい。

EJSを選択したわけ

通常のHTMLタグを使用できるので、必要な箇所だけ一部EJSの記述を取り入れれば良い。

よって学習コストが低い。
※ただし、他のテンプレートエンジンと比較して機能が少ないらしい。

今後乗り換える可能性もあるけど、もともと共通パーツを使い回せればOKだったのでEJSを使ってみることにした。

参考記事

導入方法

当方環境macのやり方なのであしからず。Windowsも流れ自体は同じ。

大まかな流れ

  1. node.jsのインストール
  2. node.jsのインストール確認(ここからターミナルを使う)
  3. タスクランナーインストール
  4. プロジェクトフォルダの設定
  5. タスクランナー を起動し、EJSファイルを編集する

node.jsのインストール

EJSにはnode.jsが必要になる。

node.jsの説明はそれだけで記事一つ以上のボリュームになってしまうが、ここでは

コンピューター上で複雑な処理をやってくれるやつ

くらいの認識でよい。

公式サイトからファイルをダウンロードする方法と、ターミナルからコマンドを入力してインストールする方法がある。

結果はどちらでも同じなので、ダウンロードする方法で進める。

node.js公式サイトから、使用しているOSの「推奨版」をダウンロードする。

保存したpkgファイルを開くとインストーラが起動するので、全てそのままで進んでインストールする。

補足:node.jsのバージョン管理する上で不便なため、ファイルをダウンロードする方法を推奨しない記事もあった。
ただ、バージョン管理ツールは後からも追加できるし、取っ掛かりとして敷居が高くなってしまうので、個人的には最初はダウンロードする方法をオススメする(そもそも他の用途がない人にはバージョン管理は不要だし)。

インストールできた。

インストールっていうと新しくアプリが追加されるイメージを持ってたけど、node.jsのインストールは「コンピューターでnode.jsを使用できる状態にする」ために行うみたい。

node.jsのインストール確認

ついにここからはターミナル(コマンドラインツール)を使用しての作業が始まる。。

ターミナルを起動すると、「(pc-name):~ (user-name)$」と表示されるので、ドルマークの後ろにコマンドを入力していく。

試しに、node.jsがちゃんとインストールされているか確認するためのコマンドを打ち込んでみる。

node -v

と打ち込んでエンター。ちゃんとインストールされていれば

v12.16.1

のように、インストールされたnode.jsのバージョンが表示される。

続けてnode.jsインストール時に同時にインストールされているはずのものを確認する。

npm -v

と打ち込んで、「6.14.11」等のバージョンを表す数字が表示されればOK。

ちなみにnpmは、node.jsの便利機能(パッケージ)を管理するためのツール。ターミナルで便利機能をインストールしたりするnpmコマンドが使えるようになる。

タスクランナーインストール

タスクランナー とは、ファイルの状態を監視して、保存された時とかに設定した処理を行ってくれるやつ。

node.jsの便利機能の一つとしてgulpという名のタスクランナーが用意されているので、npmコマンドでインストールしていく。

sudo npm install -g gulp-cli

を入力してエンター。ターミナル上でインストールが進むのでしばらく待つ。

sudo→管理者権限に
npm→npmコマンドを使って
install→インストールしますよ
-g gulp-cli→gulpをね!

という意味。

例によって下記を入力して、正常にインストールされたか確認する。

gulp -v

(現段階で「Local version undefined」の表示は問題なし)

プロジェクトフォルダの設定

前準備と予備知識

  • EJSを使用したいフォルダを用意しておく(プロジェクトフォルダと呼ぶことにする)。
  • ターミナル上で操作するフォルダへ移動する。
    →コマンドは「cd」を使用。cd+ (半角スペース)+フォルダのパス名でそのフォルダに移動する。
    ※パス名は手打ちしなくても、ターミナルにフォルダをドラッグするとフォルダのパスが入力される。

ターミナルに「cd」と「 (半角スペース)」を打って、用意したフォルダをドラッグしてエンター。

computer-name:~ username$ cd /Users/username/Desktop/files/
computer-name:files username$ 

移動が成功すると、computer-name:の後ろが移動後のフォルダ名になる。

プロジェクト用の設定ファイルの作成

npm init -y

package.jsonというファイルが作成され、「このプロジェクトではgulpを使いますよー」等の情報が保存される。

複数環境で開発する時に必須なのだけど、ここではとにかくそういうファイルを作るということだけ押さえればOK。

プロジェクトフォルダにgulp・EJS用のパッケージをインストール

プロジェクトフォルダにもgulpが必要なので下記コマンドでインストール。

npm install gulp --save-dev

EJS用のパッケージもインストールする。

npm install gulp-ejs --save-dev
npm install --save-dev gulp-rename
npm install --save-dev gulp-replace

をそれぞれ実行する。

gulp-renameは、HTMLファイルとして出力させるために必要。
gulp-replaceは不要な余白を削除するためのもの。

タスクランナーの設定ファイルを作成する

作成したフォルダにgulpfile.jsを作成する。

ここでは「こういう名前のファイルが保存されたらコンパイルしてねー」等の、監視する項目を設定する。

下記をコピペ。

var gulp = require("gulp");
var rename = require("gulp-rename");
var ejs = require("gulp-ejs");
var replace = require("gulp-replace");

// アンスコなしで始まる.ejsファイルは同階層のhtmlフォルダに出力してね
gulp.task("ejs", done => {
	gulp
		.src(["ejs/**/*.ejs", "!ejs/**/_*.ejs"])
		.pipe(ejs())
		.pipe(rename({ extname: ".html" }))
		.pipe(replace(/[\s\S]*?(<!DOCTYPE)/, "$1"))
		.pipe(gulp.dest("./html/"));
	done();
});

gulp.task('watch', function () {
    gulp.watch("ejs/**/_*.ejs", gulp.series("ejs"));
    gulp.watch("ejs/**/*.ejs", gulp.series("ejs"));
});

上記記述で、「ejsフォルダにある、拡張子ejsのファイルが保存されたら、ejsフォルダと同階層のhtmlフォルダにHTMLファイルを吐き出してね。あ、アンダースコアで始まるファイルは除外してね。」という設定ができる。

EJS用のフォルダと出力先のフォルダを作成する

EJSは拡張子ejsのファイルを保存することで、任意のフォルダにhtmlファイルが保存される。

なので、EJSファイル用のフォルダと、出力先のフォルダを作成する。

「_head.ejs」とか、アンダースコアで始まるファイルはインクルードするファイルとして使用するため「html」フォルダには出力されない。「index.ejs」ファイルを保存すると「html」フォルダにindex.htmlが保存される(階層も維持される)。

画像ファイルやJSファイルは普通に「html」フォルダに格納する。

タスクランナー を起動し、EJSファイルを編集する

長かった。。いよいよEJSで作業ができる。

ターミナルで以下を実行し、ファイル監視をスタートさせる。

npx gulp watch

監視の終了は「control+C」でできる。

EJSでの実際の書き方は次項にて。

参考記事

テンプレートエンジン「EJS」とタスクランナー「Gulp.js」で爆速HTMLコーディング | 株式会社LIG

EJSの書き方

EJS構文は<%〜%>内に記述する。

よく使う構文

// 変数を定義
<% var ejsFunc = '<p>Hello! EJS!</p>'; %>
// 配列も作れる。
<%
	var localmeta = {
		title: 'サイトタイトルです',
		desc: 'ここでサイト説明文を記入します'
	};
%>

// エスケープなしで定義した変数を出力する。基本こっちを使う
<%- ejsFunc %>
// 結果
<p>Hello! EJS!</p>

// エスケープして出力
<%= ejsFunc %>
// 結果
&lt;p&gt;Hello! EJS!&lt;/p&gt;

// ローカル変数
<% let pram = '内容'; %>

// グローバル変数
<% pram = '内容'; %>

//letの有無で決まる

// 条件分岐
<% hoge = 'text'; %>
// hogeがtrueだったら内容が表示される
<% if( hoge ) { %>
<%- hoge %>
<% } %>
// hogeが'text'だったら処理する
<% if (hoge == 'text') { %>
<% } %>

テンプレートファイル

「gulpfile.js」で設定したため、テンプレートパーツ化するファイルは「_(アンダースコア)」で始まるファイル名にすることでコンパイルの対象から外すことができる。
「_head.ejs」をインクルード書き方は下記の通り。

// .ejsは省略する
<%- include('../_head') %>

// 変数も使用できる
<% rootPath = './'; %>
<%- include(rootPath + '_head') %>

実際に書いてみる

試しに、「/ejs/about/index.ejs」ファイルを、実案件に近い形で編集してみる。

前提として、各ページファイルで使用する変数は下記とする。

<%
	title = 'ページタイトル';
	description = '説明文';
	rootPath = '../';//ルートパスを設定
	top = false;//TOPページ以外はfalse
	noindex = false;//noindexの制御
%>

インクルード用のファイルを作成。

_head.ejs

	<head>
		<meta charset="utf-8">

		<title><% if( title ) { %><%- title %> | <% } %>サイト名</title>
		<meta name="description" content="<%- description %>">
	<% if(noindex) { %>	<meta name="robots" content="noindex,nofollow"><% } %>

		<link rel="stylesheet" href="<%- rootPath %>css/style.css">

	</head>

_header.ejs

	<header class="header">
		<div class="logo"><a href="<%- rootPath %>" id="LogoImg">ロゴ</a></div>
		<nav class="nav">
			<a href="<%- rootPath %>page_1/">ページ1</a>
			<a href="<%- rootPath %>page_2/">ページ2</a>
			<a href="<%- rootPath %>page_3/">ページ3</a>
			<a href="<%- rootPath %>page_4/">ページ4</a>
		</nav>
	</header>

_footer.ejs

	<footer>
		<small class="copyWrite">&copy; company name</small>
	</footer>

about/index.ejs

<%
	title = 'アバウトページ';
	description = '説明文';
	rootPath = '../';
	noindex = false;//noindexの制御
%>

<!DOCTYPE html>
<html lang="ja">
<%- include(rootPath + '_head') %>

<body class="page">

<%- include(rootPath + '_header') %>
  <section>
    ページ内容
  </section>
<%- include(rootPath + '_footer') %>

	</body>
</html>

試しにこの状態で「about/index.ejs」を保存してみると、、(タスクランナーは起動しておくこと)。

おお、「html/about/index.html」が生成された!!

中身は、、

ちゃんとインクルードされてる!!!やったー!

参考記事

EJSの使い方!静的なHTMLサイトで「共通パーツ」と「変数」を使おう – HPcode(えいちぴーこーど)
テンプレートエンジンejsの使い方まとめ
テンプレートエンジンEJSで使える便利な構文まとめ – Qiita

他のプロジェクトでEJSを使用するときは

任意のフォルダに「package.json」と「gulpfile.js」をコピーして、ターミナルでフォルダ移動したあと、下記を実行すればOK。カンタンネー

npm install

終わりに

書いてみて、「え、こんなめんどかったっけ」って思った。

ここまでして使う意味あるの?と感じるかもしれないが、ある。確実にある。

というか、初回以外はそこまで手間ではない。使えば使うほど恩恵が大きくなるのを感じられるはずだ。

では、よいEJSライフを。