※ 2019年5月19日 EJSで<%= filename %>
でパスの取得ができなくなっているので、gulp-dataを使って、gulpfile.js内で取得する方法に変更しました。
EJSではインクルードするパスを相対パスで指定する必要があります。設定ミスを防ぐために、メタタグ内のURLなども自動化したいところです。
開発環境はmacOS High Sierra 10.13.6、Node.js 9.4.0、gulp-ejs 4.0.0で確認しています。
gulpfile
const ejs = require('gulp-ejs');
const fs = require('fs');
const data = require('gulp-data');
const rename = require('gulp-rename');
const plumber = require('gulp-plumber');
const notify = require('gulp-notify');
/**
* 開発用ディレクトリ
*/
const src = {
root: 'src/',
ejs: ['src/**/*.ejs', '!src/**/_*.ejs'],
data: 'src/_data/',
};
/**
* テスト用ディレクトリ
*/
const dest = {
root: 'htdocs/',
};
/**
* EJSをHTMLにコンパイルします。
*/
gulp.task('ejs', () => {
return gulp
.src(src.ejs)
.pipe(
data(file => {
const absolutePath = `/${file.path
.split(src.root)
[file.path.split(src.root).length - 1].replace('.ejs', '.html')
.replace(/index\.html$/, '')}`;
const relativePath = '../'.repeat([absolutePath.split('/').length - 2]);
return {
absolutePath,
relativePath,
};
}),
)
.pipe(
ejs({
site: JSON.parse(fs.readFileSync(`${src.data}site.json`)),
}),
)
.pipe(rename({ extname: '.html' }))
.pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
.pipe(gulp.dest(dest.root));
});
site
変数
サイト共通で使う変数を/src/_data/site.json
に定義します。この変数はgulpfile.jsを介して、すべてのEJSファイル内でsite.name
のように呼び出すことができます。
{
"name": "Site Title",
"description": "Site Description",
"keywords": "Site Keyword1, Site Keyword2",
"rootUrl": "http://example.com",
"ogpImage": "http://example.com/ogp-image.jpg",
"facebookAdmins": "",
"facebookAppId": "",
"twitterCard": "summary_large_image",
"twitterSite": "@SiteAccount"
}
製品リストのような別の変数を定義したい場合は、jsonファイル(/src/_data/products.json
)を作成して、gulpfile.jsで以下のように読み込んでください。
// 変更前
.pipe(
ejs(
{
site: JSON.parse(fs.readFileSync(`${src.data}site.json`)),
},
{},
{ ext: '.html' },
),
)
<%= products.items %>
のように呼び出すことができます。
// 変更後
.pipe(
ejs(
{
site: JSON.parse(fs.readFileSync(`${src.data}site.json`)),
products: JSON.parse(fs.readFileSync(`${src.data}products.json`)),
},
{},
{ ext: '.html' },
),
)
absolutePath
とrelativePath
gulpfile.jsでfs
パッケージを使用して、そのページのルート相対パスをabsolutePath
に、ルートまでの相対パスをrelativePath
に格納しています。この変数は、すべてのEJSファイル内で<%= absolutePath %>
のように呼び出せます。
index.html
は削除され、以下のように出力されます。
-
/index.ejs
で使用した場合-
<%= absolutePath %>
=>/
-
<%= relativePath %>
=> 出力なし
-
-
/products/index.ejs
で使用した場合-
<%= absolutePath %>
=>/products/
-
<%= relativePath %>
=>../
-
-
/products/product.ejs
で使用した場合-
<%= absolutePath %>
=>/products/product.html
-
<%= relativePath %>
=>../
-
site.rootUrl
と組み合わせることで、ドメインを含んだ絶対パスを出力することもできます。
<%= site.rootUrl %><%= absolutePath %>
メタタグの自動出力
共通のデータやルート相対パスなどは出力できるようになったので、メタタグも自動で生成することができます。
例えば、以下のようにindex.ejsを作成します。include()
の第二引数にpage
変数を渡して、ページごとの設定をインクルード先(src/_partial/_head.ejs
)で使えるようにしておきます。
<%
var page = {
title: "",
description: "",
ogpType: "website",
ogpImage: "",
// Do not change.
absolutePath: absolutePath,
relativePath: relativePath
};
-%>
<%- include(page.relativePath + '_partial/_head', {page: page}); %>
_head.ejsでは以下のように、page.title
を設定していればページタイトルとサイトタイトルを、page.title
がなければサイトタイトルを生成のように、テンプレートを作れます。
<% if(page.title) { %><title><%= page.title %> | <%= site.name %></title><% } else { %><title><%= site.name %></title><% } %>