EJSを使った静的サイト制作の効率アップの方法を紹介します。
EJSを使う目的
EJSはおもにHTMLページの制作をスピードアップ・効率化するためのツールです。
- EJSによるHTMLページのパーツ分割
- EJSで変数を使う方法
- EJSで配列とループを使う方法
- EJSでパスを変数化する方法
一般的にはWordPressで使うことはあまりないようです。
EJSの環境構築
EJSはgulpで使うことを前提したツールです。
EJSのインストール
EJSのインストール手順をザックリまとめると下のとおりです。
- Visual Studio Code(以下、VSCode)でサイト制作用の作業フォルダを開きます。
- VSCodeの新規ターミナルで下記コマンドを入力・リターン
npm install –save-dev gulp gulp-ejs - gulpfile.jsを新規作成、内容を編集する
一つずつ解説していきます。
VSCodeで作業フォルダを開く
サイト制作の作業フォルダの構成は人それぞれですが、今回は一例ということでご理解ください。
DEMOサイト(フォルダ)
CSS(フォルダ)
style.css
image(フォルダ)
company(フォルダ)
index.html
contact(フォルダ)
index.html
index.html
gulpとgulp-ejsのインストール
VSCodeメニューバーからでターミナル>新規ターミナルを開き、下記コマンドをVSCodeのターミナルに入力し、リターンキーを押す。
npm install --save-dev gulp gulp-ejs
インストールが成功すると下記2つのファイルと1つのフォルダが生成される。
- package.json
- package-lock.json
- node_modulesフォルダ
そして、package.jsonを開くと、下記のようにgulpとgulp-ejsがインストールされていることが確認できる。
gulpfile.jsの新規作成と編集
作業フォルダの一番上の階層にgulpfile.jsを新規作成し、下記内容を記述する。
const gulp = require("gulp");
const ejs = require("gulp-ejs");
function compileEJS() {
// コンパイル元のパス
return gulp.src(["./src/**/*.ejs", "!./src/**/_*.ejs"])
// コンパイル処理
.pipe(ejs())
// コンパイル後のパス
.pipe(gulp.dest("./public/"))
}
exports.compileEJS = compileEJS;
フォルダとファイル構成を編集
- 新たに、srcフォルダとpublicフォルダを作る
- srcフォルダに編集時に使うファイルをすべて入れ、HTMLファイルの拡張子をすべて.ejsに変える
- publicフォルダは基本そのままだが、今回は最低限htmlの生成ができればよいのでCSSとimageフォルダをassetsフォルダに入れた状態でpublicフォルダに移動
- パスが正しく動作するように編集
DEMOサイト(フォルダ)
public(フォルダ)
assets(フォルダ)
CSS(フォルダ)
style.css
image(フォルダ)
src(フォルダ)
company(フォルダ)
index.ejs
contact(フォルダ)
index.ejs
index.ejs
node_modules
gulpfile.js
package-lock.json
package.json
この状態で、ターミナルに下記コマンドを入力しリターンキーを押すと、publicフォルダ内にファイルが生成されEJSの動作確認ができる
npx gulp compileEJS
生成ファイルの拡張子のリネーム
上記のままでは、pubicフォルダ内に生成されるファイルの拡張子が.ejsになってしまうため、これを.htmlにリネームするためのパッケージ「gulp-rename」をインストールする。
- 下記コマンドをターミナルに入力リターンする。
npm install --save-dev gulp-rename
- gulpfile.jsを「gulp-rename」について下記のように追記する
const gulp = require("gulp");
const ejs = require("gulp-ejs");
const rename = require("gulp-rename");
function compileEJS() {
// コンパイル元のパス
return gulp.src(["./src/**/*.ejs", "!./src/**/_*.ejs"])
// コンパイル処理
.pipe(ejs())
.pipe(rename({extname: '.html'}))
// コンパイル後のパス
.pipe(gulp.dest("./public/"))
}
exports.compileEJS = compileEJS;
この状態でターミナルに下記コマンドを入力リターンすると、srcフォルダ内のejsファイルからpublicフォルダ内にhtmlファイルが生成されることが確認できる。
EJSの書き方(超基本)
変数
拡張子.ejsファイル内でのEJSの変数の書き方の基本を紹介します。
変数宣言
<% JavaScriptの記述 %>
例文は下記のとおり
<%
const company = “会社概要”;
%>
変数の出力の書き方
<%= 変数名 %>
注)パーツ内のごく一部で使う時はこちらの方が適している
使用例は下記の通り
<a class="header__link" href="./company/"><%= company %></a>
<%- 変数名 %>
注)パーツ全体を出力するときはこちらを使う
使用例は下記のとおり
<a class="header__link" href="./company/"><%- contact %></a>
EJSのコメントアウトの書き方
<%# コメント %>
注)コンパイルしてもコメントは出力されない
EJSの空行対策
上で紹介した記法でそのままEJSを書くとコンパイル後に空行が発生します。ここでは、この対策について紹介します。
下記のように_で挟むと_で挟まれた区間は出力されない(空行にならない)
<%_
const 変数名 = “文字列”;
_%>
例文は下記のとおり。
<%_
const company = “会社概要”;
_%>
<%#_ 変数宣言 _%>
もしくは閉じタグの前に-を入れると改行されない
<%# 変数宣言 -%>
EJSの配列とループの使い方
EJSの配列の型
例文としてヘッダーにあるグローバルメニューを使って解説します。
EJSの配列の定義
<%_
const 配列名 = [
配列
];
_%>
例文は下記のとおり
<%_
const menus = [
{
name: "会社概要",
path: "./company/index.html/"
},
{
name: "お問い合わせ",
path: "./contact/index.html/"
},
];
_%>
EJSの配列の出力
<% 配列名.forEach(配列の要素 =>{ %>
html文の中に配列として<%= 配列の要素.キー %>を入れる
<% }) %>
例えば、上で定義した配列をnavタグ内にループで出力する場合には下記のようになる
<nav class="header-nav">
<% menus.forEach(menu =>{ %>
<a class="header__link" href="<%= menu.path %>"><%= menu.name %></a>
<% }) %>
</nav>
さらに空行対策して下記のように_で囲むと良い
<%_ menus.forEach(menu =>{ _%>
<a class="header__link" href="<%= menu.path %>"><%= menu.name %></a>
<%_ }) _%>
このように配列を利用すると、メニュー項目が増えたときも記述量が少なく済みミスも減るので良い。下記のように最初に増えた分の配列を定義してしまえば、htmlが自動生成されるため非常に便利である。
<%_
const menus = [
{
name: "会社概要",
path: "./company/index.html/"
},
{
name: "サービス",
path: "./service/index.html/"
},
{
name: "お知らせ",
path: "./news/index.html/"
},
{
name: "お問い合わせ",
path: "./contact/index.html/"
},
];
_%>
EJSのパーツ分割
基本構文|EJSのパーツ分割
EJSの基本操作は下記のとおりです。
- ejsファイルのパーツ化したい部分を別のejsファイルにカット&ペースト
- 元ejsファイルのカットして空いた場所に下記構文を入れる
<%- include(“パス”) %>
例文:footerをパーツ化する場合
- footer.ejsを新規作成する(通常はsrcフォルダ内にpartsフォルダを新設し、その中に新規作成する)。
DEMOサイト(フォルダ)
public(フォルダ)
assets(フォルダ)
CSS(フォルダ)
style.css
image(フォルダ)
src(フォルダ)
company(フォルダ)
index.ejs
contact(フォルダ)
index.ejs
parts(フォルダ)
footer.ejs
index.ejs
node_modules
gulpfile.js
package-lock.json
package.json
2. footer.ejsの内容:元のindex.ejsからそのままカット&ペースト(インデントの調整必要)
<footer class="footer">
<div class="footer__inner inner">
<div class="footer__copyright">Copyright © 2023 Logo All rights reserved.</div>
</div>
</footer>
</body>
</html>
注意:</body>と</html>の閉じタグまで含める
元のindec.ejsは下記のとおり(下記は完成形)
<%- include("./parts/_footer") %>
下記は完成形全文
<%- include("./parts/_header", {
title: "DEMOサイト",
description: "トップページのディスクリプション",
path: "."
}) -%>
<%- include("./parts/_main-visual-top") -%>
<div class="section">
<div class="inner">
<h2 class="section__title">セクション</h2>
<div class="section__lead">Section</div>
<div class="section__body">
<p>会社概要のコンテンツが入ります。</p>
</div>
</div>
</div>
<%- include("./parts/_footer") %>
例文:ヘッダー(メニューあり)をパーツ化する場合
header.ejs全文の完成形は下記のとおりだが、下記ではパスの変数化も行っている
<%# 変数宣言 -%>
<%_
const menus = [
{
name: "会社概要",
path: `${path}/company/index.html`
},
{
name: "お問い合わせ",
path: `${path}/contact/index.html`
},
];
_%>
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><%= title %></title>
<meta name="description" content="<%= description %>">
<!-- Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700;900&display=swap" rel="stylesheet">
<!-- CSS -->
<link rel="stylesheet" href="<%= path %>/assets/css/style.css">
</head>
<body>
<header class="header">
<div class="header__inner inner">
<h1 class="header__logo"><a href="<%= path %>/index.html">Logo</a></h1>
<nav class="header__nav">
<%_ menus.forEach(menu =>{ _%>
<a class="header__link" href="<%= menu.path %>"><%= menu.name %></a>
<%_ }) _%>
</nav>
</div>
</header>
元のindex.ejsはfooterの箇所を参照してください。
トップページと下層ページでタイトルとディスクリプションを別々に設定したいとき
トップページ
index.ejs
<%- include("./parts/_header", {
title: "DEMOサイト",
description: "トップページのディスクリプション",
path: "."
}) -%>
<%- include("./parts/_main-visual-top") -%>
<div class="section">
<div class="inner">
<h2 class="section__title">セクション</h2>
<div class="section__lead">Section</div>
<div class="section__body">
<p>会社概要のコンテンツが入ります。</p>
</div>
</div>
</div>
<%- include("./parts/_footer") %>
header.ejsの抜粋
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><%= title %></title>
<meta name="description" content="<%= description %>">
下層ページ
トップページとの違いはパス。
<%- include("../parts/_header", {
title: "会社概要",
description: "会社概要ページのディスクリプション",
path: ".."
}) -%>
<div class="main-visual">
<div class="main-visual__content">
<div class="main-visual__text">会社概要</div>
</div>
</div>
<div class="section">
<div class="inner">
<h2 class="section__title">会社概要</h2>
<div class="section__lead">Company</div>
<div class="section__body">
<p>会社概要のコンテンツが入ります。</p>
</div>
</div>
</div>
<%- include("../parts/_footer") %>
header.ejsはトップページと共通
HTMLを整形するパッケージのインストール
下記コマンドをターミナルに入力リターン
npm install --save-dev gulp-html-beautify
gulpfile.jsに下記を追記
const htmlBeautify = require(“gulp-html-beautify”);
.pipe(htmlBeautify())
const gulp = require("gulp");
const ejs = require("gulp-ejs");
const rename = require("gulp-rename");
const htmlBeautify = require("gulp-html-beautify");
function compileEJS() {
// コンパイル元のパス
return gulp.src(["./src/**/*.ejs", "!./src/**/_*.ejs"])
// コンパル処理
.pipe(ejs())
.pipe(rename({extname: '.html'}))
.pipe(htmlBeautify())
// コンパイル後のパス
.pipe(gulp.dest("./public/"))
}
exports.compileEJS = compileEJS;
EJSのパスの配列化
パスを配列に加えることにより、ページごとのパスの設定を一部自動化できる。
header.ejs
ejs構文中に変数を入れる場合は書き方が特殊なので注意する
`${変数} …….`という書き方に変える。
path: `${path}/company/index.html`
以下、配列の定義部分の抜粋
<%_
const menus = [
{
name: "会社概要",
path: `${path}/company/index.html`
},
{
name: "お問い合わせ",
path: `${path}/contact/index.html`
},
];
_%>
本文中は下記のように代入する。
<%= 変数名 %>
<%= path %>
本文中の関係箇所抜粋
<!-- CSS -->
<link rel="stylesheet" href="<%= path %>/assets/css/style.css">
全文抜粋:上記CSSに他にH1タグのリンクも配列の変数に置き換えている。
<%# 変数宣言 -%>
<%_
const menus = [
{
name: "会社概要",
path: `${path}/company/index.html`
},
{
name: "お問い合わせ",
path: `${path}/contact/index.html`
},
];
_%>
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><%= title %></title>
<meta name="description" content="<%= description %>">
<!-- Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700;900&display=swap" rel="stylesheet">
<!-- CSS -->
<link rel="stylesheet" href="<%= path %>/assets/css/style.css">
</head>
<body>
<header class="header">
<div class="header__inner inner">
<h1 class="header__logo"><a href="<%= path %>/index.html">Logo</a></h1>
<nav class="header__nav">
<%_ menus.forEach(menu =>{ _%>
<a class="header__link" href="<%= menu.path %>"><%= menu.name %></a>
<%_ }) _%>
</nav>
</div>
</header>
index.ejs(トップページ)
配列の定義に「path: “.”」を追記する必要あり。
<%- include("./parts/_header", {
title: "DEMOサイト",
description: "トップページのディスクリプション",
path: "."
}) -%>
<%- include("./parts/_main-visual-top") -%>
index.ejs(下層ページ)
配列の定義に「path: “..”」を追記する必要あり。
<%- include("../parts/_header", {
title: "会社概要",
description: "会社概要ページのディスクリプション",
path: ".."
}) -%>
EJSをテンプレとして他のプロジェクトで使い回す方法
EJSのフォルダとファイル構造
作業用フォルダ
public(フォルダ) ←コンパイル後のhtmlファイルが生成されるフォルダ
assets(フォルダ)
CSS(フォルダ)
style.css
image(フォルダ)
src(フォルダ) ←開発用のファイルを入れるフォルダ
company(フォルダ)
index.ejs ←下層ページ
contact(フォルダ)
index.ejs ←下層ページ
parts(フォルダ) ←共通パーツフォルダ
_header.ejs ←共通パーツファイル
_footer.ejs ←共通パーツファイル
_main-visual-top.ejs ←共通パーツファイル
index.ejs ←トップページ
gulpfile.js ←コピペで作る
package.json ←コピペで作る
gulpfile.jsを作る
gulpfile.jsに下記コードをすべてコピペすれば、使えます。
const gulp = require("gulp");
const ejs = require("gulp-ejs");
const rename = require("gulp-rename");
const htmlBeautify = require("gulp-html-beautify");
function compileEJS() {
// コンパイル元のパス
return gulp.src(["./src/**/*.ejs", "!./src/**/_*.ejs"])
// コンパル処理
.pipe(ejs())
.pipe(rename({extname: '.html'}))
.pipe(htmlBeautify())
// コンパイル後のパス
.pipe(gulp.dest("./public/"))
}
exports.compileEJS = compileEJS;
package.jsonを作る
package.jsonに下記コードをすべてコピペすれば、使えます。
{
"devDependencies": {
"gulp": "^4.0.2",
"gulp-ejs": "^5.1.0",
"gulp-html-beautify": "^1.0.1",
"gulp-rename": "^2.0.0"
}
}
EJSをインストールする
VSCodeのターミナルに下記コマンドを入力リターンすると、EJSに必要なファイルがインストールされる。
npm install
具体的には、node_modulesフォルダとpackage-lock.jsonが新たにインストールされる。
各種EJSテンプレートファイル
ここで紹介するテンプレートファイルは、必要に応じて内容を変更して下さい。
EJSのコンパイルコマンド
VSCodeのターミナルに下記コマンドを入力リターンすると、ejsファイルからhtmlファイルにコンパイルされる。
npx gulp compileEJS
index.ejs|トップページ
<%- include("./parts/_header", {
title: "DEMOサイト",
description: "トップページのディスクリプション",
path: "."
}) -%>
<%- include("./parts/_main-visual-top") -%>
<div class="section">
<div class="inner">
<h2 class="section__title">セクション</h2>
<div class="section__lead">Section</div>
<div class="section__body">
<p>会社概要のコンテンツが入ります。</p>
</div>
</div>
</div>
<%- include("./parts/_footer") %>
index.ejs|下層ページ
<%- include("../parts/_header", {
title: "会社概要",
description: "会社概要ページのディスクリプション",
path: ".."
}) -%>
<div class="main-visual">
<div class="main-visual__content">
<div class="main-visual__text">会社概要</div>
</div>
</div>
<div class="section">
<div class="inner">
<h2 class="section__title">会社概要</h2>
<div class="section__lead">Company</div>
<div class="section__body">
<p>会社概要のコンテンツが入ります。</p>
</div>
</div>
</div>
<%- include("../parts/_footer") %>
_header.ejs|共通パーツのヘッダー
<%# 変数宣言 -%>
<%_
const menus = [
{
name: "会社概要",
path: `${path}/company/index.html`
},
{
name: "お問い合わせ",
path: `${path}/contact/index.html`
},
];
_%>
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><%= title %></title>
<meta name="description" content="<%= description %>">
<!-- Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700;900&display=swap" rel="stylesheet">
<!-- CSS -->
<link rel="stylesheet" href="<%= path %>/assets/css/style.css">
</head>
<body>
<header class="header">
<div class="header__inner inner">
<h1 class="header__logo"><a href="<%= path %>/index.html">Logo</a></h1>
<nav class="header__nav">
<%_ menus.forEach(menu =>{ _%>
<a class="header__link" href="<%= menu.path %>"><%= menu.name %></a>
<%_ }) _%>
</nav>
</div>
</header>
_footer.ejs|共通パーツのフッター
<footer class="footer">
<div class="footer__inner inner">
<div class="footer__copyright">Copyright © 2023 Logo All rights reserved.</div>
</div>
</footer>
</body>
</html>
_main-visual-top.ejs|共通パーツのコンテンツ
<div class="main-visual is-top">
<div class="main-visual__content">
<div class="main-visual__text">トップページ</div>
</div>
</div>