EJS:インクルードしたファイル内で相対パスを設定する方法

Tips

EJS:インクルードしたファイル内で相対パスを設定する方法

EJSで特定のファイルを共通ファイルとしてインクルードさせるとき、その共通ファイル内にあるパス指定部分にページ毎で異なる相対パスを設定させる方法で、インクルード時の引数を利用する方法としない方法とで2パターン紹介します。

※以下で紹介する方法はgulpを使用して実装する方法になりますので、予めgulpが使用できる環境を用意してください。

※EJSの基本的な使用方法などについては省略しているので、「EJS -- Embedded JavaScript templates」や「GitHub - mde/ejs: Embedded JavaScript templates」などで確認してください。

使用するプラグインとファイル構成

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

今回はgulpでEJSを使用するので、まず下記コマンドで「gulp-ejs」をインストールします。

$ npm i -D gulp-ejs

ファイル構成

ここで使用する方法は以下のようなファイル構成のものを使用した想定になり、後述するコード内のパスなどについてもこの構成をもとにしています。
/src直下のindex.ejsがTOPページ、/src/pageindex.ejsは下層ページ扱いとして、いずれも共通ファイルである/src/templates/_nav.ejsを読み込んで表示させるというものになり、この_nav.ejs内にあるパス指定を相対パスになるようにしていきます。

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

インクルードの引数を利用する

タスクの記述

タスクは特別な記述などは必要なく、単純に/srcgulp.dest()するという感じで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に共通ファイルとして読み込む/src/templates/_nav.ejsをインクルードさせ、その際includeには引数として後ほど相対パスとして利用するパスを記述しておきます。
今回のサンプルの場合はそれぞれ下記のようになります。

/src/index.ejs

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

/src/page/index.ejs

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

次にインクルードするように指定した_nav.ejsの作成で、今回はファイル名にもあるようにナビゲーションが記述されたファイルと想定して、ベースとなるHTMLとしては下記のようなものを使用します。

HTML

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

ベースHTMLにあるa要素のhrefにはどちらもルート相対パスで指定されていますが、このパス部分を下記のように頭にある/<%= path; %>に変更し、こうすることで先ほどインクルード時に引数として記述したものがここに出力されます。

/src/templates/_nav.ejs

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

あとは$ gulp ejs/srcの並列に出力される/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に下記のように記述し、こちらの場合はEJSの処理の他に「gulp-data」の読み込みと処理を追加します。

gulpfile.js

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に共通ファイルとして読み込む/src/templates/_nav.ejsをインクルードさせ、今回のサンプルの場合はそれぞれ下記のようになります。

/src/index.ejs

<% include ./templates/_nav %>

/src/page/index.ejs

<% include ../templates/_nav %>

次にインクルードするように指定した_nav.ejsの作成で、今回はファイル名にもあるようにナビゲーションが記述されたファイルと想定して、ベースとなるHTMLとしては下記のようなものを使用します。

HTML

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

ベースHTMLにあるa要素のhrefにはどちらもルート相対パスで指定されていますが、このパス部分を相対パスになるようにするために_nav.ejsは下記のような記述をします。

/src/templates/_nav.ejs

<%
  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>

コード上部は相対パスを出力するための処理を行っており、ファイルパスを取得する際に以前(v2.3.0など)は<%= filename %>で取得できたのが現在(v3.0.1)は取得できなくなっているために、ここで「gulp-data」を使って取得したファイルパスを利用します。
行っている処理の内容としては取得したパスを任意の部分(このサンプルの場合は'src/ejs')で分割してから階層を調べ、その数に応じて相対パスを出力するといったものになります。

パスを出力させたい部分には<%= path(); %>といった形で記述し、単純に記述した場合は./../などが出力されますが、例えば<%= path('page/'); %>のように引数を付けて記述した場合は./page../page/などのように、ディレクトリ名やファイル名付きで出力させることができます。
<%= path(); %>page/のような形でも可)

あとは$ gulp ejs/srcの並列に出力される/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>

この実装方法については以下を参考にさせてもらいました。

Posted on

Category : Tips

Close the search window,
please press close button or esc key.