EJSでファイルをインクルードして相対パスを使う方法

今回はEJSでファイルをインクルードして相対パスを使う方法を紹介します。

ファイルを共通ファイルとしてインクルードし、そのファイル内にあるパス指定部分でページごとに異なる相対パスを設定する方法です。やり方は2種類あります。

また、gulpを使用するのであらかじめgulpをインストールしておいてください。

 

プラグインをインストール

gulpでEJSを使うならまずはgulp-ejsをインストールします。以下のコマンドを入力します。

$ npm i -D gulp-ejs

 

ファイル構成

以下のようなファイル構成にします。

/src/ejsのindex.ejsがトップページ、/src/pageのindex.ejsは下層ページ、共通ファイルは/src/ejs/templates/_nav.ejsとなっています。

_nav.ejs内にパスを相対パスで指定します。

├─ /src
│  └─ /ejs
│      ├─ index.ejs
│      ├─ /page
│      │  └─ index.ejs
│      └─ /templates
│          └─ _nav.ejs
└─ gulpfile.js

 

タスクを指定

gulpfile.jsにタスクを登録していきます。gulpfile.jsの書き方はある程度決まっています。

以下のように記述しましょう。

var gulp = require( 'gulp' ),
    ejs = require( 'gulp-ejs' );

gulp.task('ejs', function() {
  return gulp.src(['src/ejs/**/*.ejs', '!src/ejs/**/_*.ejs'])
      .pipe(ejs({}, {}, {ext: '.html'}))
      .pipe(gulp.dest('dist'));
});

 

EJSを記述

まずは各index.ejsに_nav.ejsをインクルードし、引数には相対パスを記述しておきます。

/src/index.ejs

<%-
  include('./templates/_nav', {
    path: './'
  });
%>

 

/src/page/index.ejs

<%-
  include('../templates/_nav', {
    path: '../'
  });
%>

 

次に_nav.ejsを記述します。

名前の通りナビゲーションをHTMLで記述していきましょう。

<nav>
  <a href="/">home</a>
  <a href="/page/">page</a>
</nav>

 

以下のような書き方でも大丈夫です。

この場合、index.ejsにインクルードした時の相対パスが出力されます。

<nav>
  <a href="<%= path; %>">home</a>
  <a href="<%= path; %>page/">page</a>
</nav>

 

そうしたら$ gulp ejsコマンドでコンパイルしてしまえばdistの中にHTMLとして出力されます。

それぞれが異なる相対パスでインクルードされているのが確認できると思います。

/dist/index.html

<nav>
  <a href="./">home</a>
  <a href="./page/">page</a>
</nav>

 

/dist/page/index.html

<nav>
  <a href="../">home</a>
  <a href="../page/">page</a>
</nav>

 

別のやり方

もう一つのやり方はインクルード時にパスを引数に記述せず、パスを取得して処理をさせることでパスを出力するという方法です。

 

プラグインをインストール

ファイルのパスを取得するためにgulp-dataを使います。

まずは以下のコマンドでインストールしてしまいましょう。

$ npm i -D gulp-data

 

タスクを指定

gulpfile.jsにタスクを指定していきます。

gulp-ejsに加え、gulp-dataも使うので以下のようになります。

var gulp = require( 'gulp' ),
    ejs = require( 'gulp-ejs' ),
    data = require( 'gulp-data' );

gulp.task('ejs', function() {
  return gulp.src(['src/ejs/**/*.ejs', '!src/ejs/**/_*.ejs'])
      .pipe(data(function(file) {
        return { 'filename': file.path }
      }))
      .pipe(ejs({}, {}, {ext: '.html'}))
      .pipe(gulp.dest('dist'));
});

 

EJSを記述

各index.ejsに_nav.ejsをインクルードさせます。

今回は以下のようになります。

/src/index.ejs

<% include ./templates/_nav %>

 

/src/page/index.ejs

<% include ../templates/_nav %>

 

インクルードさせる_nav.ejsはナビゲーションを想定して以下のように書きましょう。

<nav>
  <a href="/">home</a>
  <a href="/page/">page</a>
</nav>

 

href属性の中のパスを変更します。

パスを取得して相対パスとして出力できるように以下のように記述を加えましょう。href属性もパスが処理されて出力されるようにします。

<%
  path = function(fileName) {
    var depth = filename.replace(/\\/g, '/').split('src/ejs')[1].split('/').length - 2;
    var path = depth > 0 ? '../'.repeat(depth) : './';
    if ( fileName !== undefined ) {
      path += fileName;
    }
    return path;
  };
-%>
<nav>
  <a href="<%= path(); %>">home</a>
  <a href="<%= path('page/'); %>">page</a>
</nav>

 

コードの上部でパスを出力する処理を行っています。以前のバージョンでは<%= filename %>でパスを取得することができましたが、現在のバージョンでは使えないのでファイルパスを取得する際にgulp-dataを使用しています。

行っている処理をざっくり説明すると、取得したパスを任意の部分(このサンプルの場合は’src/ejs’)で分割してから階層の深さを調べ、その数に応じて相対パスを出力するという処理です。

パスは<%= path(); %>の部分に出力され、相対パスになります。

任意のディレクトリを加えたい場合は<%= path(‘page/’); %>のように引数をつけて記述します。この場合、./pageや../page/などのように、ディレクトリ名をつけて出力ができます。

 

そうしたら$ gulp ejsコマンドで/distに出力されるHTMLを確認するとそれぞれが異なる相対パスでインクルードできているのが確認できると思います。

/dist/index.html

<nav>
  <a href="./">home</a>
  <a href="./page/">page</a>
</nav>

 

/dist/page/index.html

<nav>
  <a href="../">home</a>
  <a href="../page/">page</a>
</nav>