EJS を使用し、header や footer 等の共通部分を外部から呼び出す場合、インクルード元のファイルの階層が違うと、相対パスのリンクが切れてしまいます。
今回は、あらゆる階層から呼び出されても階層にあわせて相対パスが変わるように、EJS ファイルに変数を割り当てる方法を説明したいと思います。
目次
- Gulp4 + EJS のインクルードファイルの相対パスを変数化する
- まとめ
Gulp4 + EJS のインクルードファイルの相対パスを変数化する
以下のような階層構造で、index.ejs と page.ejs がともに header.ejs をインクルードした場合のサンプルコードとなります。
ファイルツリー
[code]
project
├ gulpfile.js
├ pubric
│ ├ …
│ └ …
└ src
└ ejs
├ _data
│ └ site.json
├ _partial
│ └ header.ejs
├ _pages
│ └ page.ejs
└ index.ejs
[/code]
gulpfile.js
[code]
const fs = require(‘fs’);
const gulp = require(‘gulp’);
const data = require(‘gulp-data’);
const ejs = require(‘gulp-ejs’);
const notify = require(‘gulp-notify’);
const plumber = require(‘gulp-plumber’);
// paths
const paths = {
src: ‘src/’,
dest: ‘public/’,
root: ‘src/ejs/’,
data: ‘src/ejs/data/’
}
// EJS
gulp.task(‘ejs’, () => {
var ts = Date.now();
return gulp.src([paths.src + “ejs/**/*.ejs”, ‘!’ + paths.src + “ejs/**/_*.ejs”])
.pipe(
data(file => {
const absolutePath = `/${file.path
.split(paths.root)
[file.path.split(paths.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(`${paths.data}site.json`)),
}),
)
.pipe(ejs({}, {}, {
ext: ‘.html’
}))
.pipe(replace(/__NOCACHE__/g, ts)) //replace __NOCACHE__
.pipe(plumber({
errorHandler: notify.onError(‘Error: <%= error.message %>‘)
}))
.pipe(gulp.dest(paths.dest));
});
[/code]
site.json
サイト全体で使用するデータです。主に head タグ内で利用するものを記述しています。
(例)<%= site.name %> で “Your Sitename” が出力
[code]
{
“name”: “Your Sitename”,
“description”: “Your Site Description”,
“keywords”: “Site Keyword1, Site Keyword2”,
“rootUrl”: “/”,
“ogpImage”: “http://example.com/ogp-image.jpg”,
“facebookAdmins”: “”,
“facebookAppId”: “”,
“twitterCard”: “summary_large_image”,
“twitterSite”: “@SiteAccount”
}
[/code]
header.ejs
[code]
<%
var page = {
absolutePath: absolutePath,
relativePath: relativePath
};
-%>