5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ちょっとがんばるWebサイト開発 on Webpack5 - EJSを導入して効率的にHTMLファイルを生成する

Last updated at Posted at 2023-03-08

前書き

本記事のゴール

この記事では、EJS テンプレートを利用することで、HTMLのコーディングの効率を向上させる方法を理解することを目指します。

この記事で解説する内容

  • EJSの概要について説明します
  • EJSをプロジェクトに導入する方法について説明します
  • EJSを利用した簡単な実例を紹介します

この記事で解説しない内容

  • EJSの詳細な文法については説明しません
  • EJSテンプレートで外部JSONデータを活用する方法については説明しません

[参考] EJSの文法に関する詳細説明

シリーズ記事

この記事はシリーズ 「ちょっとがんばるWebサイト開発 on Webpack5」 の記事です。
シリーズ全体の概要は 以下のリンク先記事 にまとめられています。

この記事では Webpack5 (version5.X.X) を対象としています。

背景知識

EJSとは何か

EJS (Embedding JavaScript template) は、HTMLファイルを生成するテンプレートを記述するための言語仕様です。HTML形式をベースに記述されており、そこにJavaScriptの構文を挿入することができます。JavaScriptの構文が利用できるため、条件分岐やループ等を用いてHTML要素の宣言をコントロールすることができます。

EJSファイルは、HTMLファイルを生成するための「テンプレート」として利用します。EJSファイルそれ自体はWebサーバにアップロードせず、コンパイルした結果得られるHTMLファイルを公開するという形で利用します。

この記事ではWebpackを利用してプロジェクトにEJSを導入するところに焦点を当てるため、EJSの詳細には立ち入りません。

[参考] EJS関連記事

EJSを使うと何が良いのか

HTML形式には文書構造を宣言するための限られた構文しか用意されていないため、生のHTMLファイルを記述する際に不都合が生じることは多いと思います。

例えば、GitHubユーザのレポジトリ一覧 に見られるように、ほとんど同一の構造を持つHTML要素を多数並べたいという状況が考えられます。1 こうした状況において、各種プログラミング言語で実装されている「ループ(JavaScriptにおけるfor文)」の機能を活用して記述できるとすれば、より効率的で保守性の高いコーディングができるでしょう。

生のHTML/CSS/JavaScript2 のみで静的Webサイトを開発した経験がある人ならば誰しも一度は「HTMLのコーディングでもプログラミング言語のような記述をしたい」と考えたことがあると思いますが、EJSはそれを実現する1つのアプローチとなっています。

EJSを使う必要があるのか

EJS以外の技術でEJS同様の処理を実行することについて考えてみます。

1つ目は既存のHTMLテンプレートエンジンを利用する方法です。

EJS同様に広く利用されているHTMLテンプレートエンジンとしては Pug というものがあるようです。JavaScriptテンプレートエンジンのPug(Jade)とEJSの比較 - Qiita 等の記事で確認できるように、EJSとPugの記法は大きく異なるため、自分の好みに合わせてテンプレートエンジンを選ぶと良いでしょう。

[参考] Pug関連記事

2つ目はプロジェクトに特化したHTMLテンプレートエンジンを自作する方法です。

EJSのコンパイラがやっていることは「部分的にJavaScriptコードが挿入されたHTMLファイルをEJSの言語仕様に則って生のHTMLファイルに変換する」という作業です。ということは、適当な言語仕様とコンパイラさえ用意することさえできれば、EJS同様の処理を実行することは難しくありません。「言語仕様(ルール)」「コンパイラ(変換器)」といっても、自身のプロジェクトで必要な最低限のルールと任意のプログラミング言語で実装された変換器が用意できれば十分でしょう。
この意味で、「EJSを導入するほど複雑な処理を行わない」「EJSでは実現できない特殊な処理を行いたい」という場合には自分で実装するというのも1つの選択肢になるかと思います。

3つ目はHTMLテンプレートエンジン以外の技術を利用する方法です。

最近では Vue, React, Angular 等のJavaScriptフロントエンドフレームワークを用いる場合が増えてきているようです。これらのフレームワークは通常HTML要素を 動的に 生成するため、HTMLファイルを 静的に 生成するEJSの技術とは一線を画す存在となっています。3 これらの技術の差異について理解しておくと後々役に立つような気がします。

「HTML要素/ページを 静的に 生成する」とは、ローカル環境においてEJS等のソースファイルをコンパイルすることで事前にHTML要素/ファイルを生成しておくことを指しています。一方で「HTML要素/ページを 動的に 生成する」とは、Webページがアクセスされた際にサーバにおいてHTML要素/ファイルを生成することを指しています。どちらのアプローチをとるべきかは、Webサイトの特性等を考慮して決定します。

[参考] JavaScriptフロントエンドフレームワーク

方法

サンプルコードをGitHubで公開しています。記事と併せてご覧ください。
/website/website-dev-on-webpack5/ejs-on-webpack5

実装例の説明では、ファイル/フォルダパスを ルート相対パス の形式で記述しています。ここでルートはプロジェクトルートまたはWebサイトのドキュメントルートに相当します。

準備

WebpackおよびEJS等のnpmパッケージの利用には Node.js が必要です。
インストールが未実施の場合には、以下のリンクからインストールしておいてください。

また、動作確認を行うための Node.js プロジェクトを作成しておきます。
適当な名前のディレクトリ(ここでは my-ejs-project )を用意した上で、そのディレクトリにおいて npm init コマンドを実行することで Node.js プロジェクトを新規作成することができます。

ターミナル
# my-ejs-projectディレクトリの作成
$ mkdir /path/to/my-ejs-project
$ cd /path/to/my-ejs-project

# Node.jsプロジェクトの作成
$ npm init

npm init コマンドを実行するとプロジェクトに関する情報を入力するよう促されますが、今回は適当な設定にしておいて問題ありません。今後必要に応じて適宜変更しましょう。
コマンド実行完了後、 /package.json という設定ファイルが新規作成されていることを確認したら事前準備完了です。

手順概要

  1. npmパッケージを導入する
    EJSからHTMLを生成するのに必要なnpmパッケージ webpack webpack-cli html-webpack-plugin html-loader template-ejs-plugin をプロジェクトに追加します。

  2. Webpackの設定ファイルを記述する
    EJSからHTMLを生成する手順やルールを設定ファイル /webpack.config.js に記述します。

  3. EJSファイルを作成する
    HTMLファイルのテンプレートとなるEJSファイル /src/source.ejs を作成します。

  4. EJSファイルをコンパイルしてHTMLファイルを生成する
    Webpackを実行することでEJSファイルのコンパイルを実行し、HTMLファイル /dist/target.html を生成します。

[手順1] npmパッケージを導入する

今回は Webpack を利用してEJSファイルのコンパイルを行います。

まず初めに、Webpackを利用するのに必要な webpack webpack-cli パッケージをインストールします。
Webpack5(version5.X.X)をインストールするため、バージョン指定を行っています。

ターミナル
npm install --save-dev webpack@5 webpack-cli@5

次に、EJSファイルをコンパイルするのに必要な html-webpack-plugin html-loader template-ejs-loader パッケージをインストールします。

ターミナル
npm install --save-dev html-webpack-plugin html-loader template-ejs-loader

[手順2] Webpackの設定ファイルを記述する

Webpackは、適切に設定を記述することで様々な処理を実行することができます。
ここではEJSファイル /src/source.ejs をコンパイルして /dist/target.html を生成するための必要最小限の設定を示します。

/webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = function() {
  return {

    mode: "development",

    entry: {},

    output: {
      /**
       * OUTPUT_DIRECTORY = /dist
       */
      path: path.resolve(__dirname, "dist"),
    },

    module: {
      rules: [
        {
          test: /\.ejs$/,
          use: [
            /**
             * HtmlLoader -> TemplateEjsLoader
             */ 
            "html-loader",
            "template-ejs-loader",
          ],
        },
      ]
    },
    
    plugins: [
      new HtmlWebpackPlugin({
        template: path.resolve(__dirname, "src", "source.ejs"),
        filename: "target.html",
        minify: {
          collapseWhitespace: true,
          preserveLineBreaks: true,
        },
      }),
    ],

  }
}

上記のWebpack設定には同シリーズ別記事 「ちょっとがんばるWebサイト開発 on Webpack5 - HTMLをコピー&ペーストする」 と共通する部分が多数あります。共通部分に関する説明として、同シリーズ別記事の説明を一部改変して引用したものを載せておきます。

上記の設定を要約すると、
Webpackのプラグイン設定箇所に、適切な設定を含む HtmlWebpackPlugin({...}) オブジェクトを追加する
となります。特に注目すべきパラメータは以下の通りです。

  • template: path.resolve(__dirname, "src", "source.html")
    入力HTMLファイルの 絶対パス を指定する

  • filename: "target.html"
    出力HTMLファイルの 相対パス を指定する

注目すべき最も大きな相違点はWebpackのルール設定です

Webpackは、ルール設定で指定された内容に従って最適化/変換処理等を行います。
{ test: /\.ejs$/ } および { use: [ "html-loader", "template-ejs-loader" ] } という設定を記述することで、拡張子 *.ejs のファイルに対して ejs-template-loader の変換処理と html-loader の変換処理をこの順で適用することができます。
大雑把に言えば、 template-ejs-loader はEJSテンプレートをコンパイルしてHTMLページを生成するもので、 html-loadertemplate-ejs-loader 等の出力結果をWebpackのビルドプロセスで取り扱えるようにするものです(この記事では詳細を割愛します)。

HtmlWebpackPluginプラグインでは、デフォルトでEJSローダーが適用されることになっているため、より簡潔な記述でもEJSテンプレートファイルを取り扱うことができます。例えば、 webpack.config.js を以下のように記述することができます(折りたたみ要素の中にあります)。

/webpack.config.js の設定内容例
webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = function() {
  return {

    mode: "development",

    entry: {},

    output: {
      path: path.resolve(__dirname, "dist"),
    },
    
    plugins: [
      new HtmlWebpackPlugin({
        template: path.resolve(__dirname, "src", "source.ejs"),
        filename: "target.html",
        minify: {
          collapseWhitespace: true,
          preserveLineBreaks: true,
        },
      }),
    ],

  }
}

例において webpack webpack-cli html-webpack-plugin プラグインは必要ですが、 html-loader template-ejs-loader プラグインは不必要であるため、インストールの手間を削減することができます。

ただし、 デフォルトのEJSローダーはEJSの構文すべてをサポートしているわけではないことに注意してください 。EJSの構文すべてを扱うためには、追加プラグイン html-loader ejs-template-plugin の導入および追加設定を行います。詳細はHtmlWebpackPluginの公式ドキュメントに詳しいです。

[参考]

[参考] Webpack設定

[参考] html-webpack-plugin / html-loader / template-ejs-loader

[手順3] EJSファイルを作成する

手順2の設定に従ってEJSファイルを作成します。
上記設定ファイル /webpack.config.js では入力EJSファイルパスを /src/source.ejs に指定したので、その位置に source.ejs ファイルを作成しましょう。
ファイル内容はどんなものでも構いませんが、ここでは例として以下のように記述することにします(折りたたみ要素の中にあります)。

/src/source.ejs の入力内容例
/src/source.ejs
<!doctype html>
<html>
  <head>
    <title>My EJS Project</title>
  </head>
  <body>
    <h1>Hello, Webpack!</h1>
    <ul>
      <% let plugins = [ "html-webpack-plugin", "html-loader", "template-ejs-loader" ]; %>
      <% for (let idx = 0; idx < plugins.length; idx++) { %>
        <li><p>Hello, <%= plugins[idx] %>!</p></li>
      <% } %>
    </ul>
  </body>
</html>

[手順4] EJSファイルをコンパイルしてHTMLファイルを生成する

手順1〜3でEJS→HTML変換のための準備が完了しました!
それではWebpackを用いて /src/source.ejs から /dist/target.html を生成してみましょう。
ターミナルで npx webpack コマンドを実行することでビルド作業が開始します。

ターミナル
# ディレクトリ移動
cd /path/to/my-ejs-project

# Webpackコマンド実行
npx webpack

ビルドが正常に完了すれば、HTMLファイル /dist/target.html が生成されていることを確認できると思います。ファイルの内容を確認すると、EJSで記述された部分が展開されてHTMLになっているはずです(折りたたみ要素の中にあります)。

 /dist/target.html の出力内容例
/dist/target.html
<!doctype html>
<html>
<head>
<title>My EJS Project</title>
</head>
<body>
<h1>Hello, Webpack!</h1>
<ul>
<li><p>Hello, html-webpack-plugin!</p></li>
<li><p>Hello, html-loader!</p></li>
<li><p>Hello, template-ejs-loader!</p></li>
</ul>
</body>
</html>

上記手順では、Webpackを利用してEJSをコンパイルする方法を示しましたが、Webpackを利用しないで実現する方法もあります。
EJS公式サイト にも書かれているように、npmパッケージ ejs を導入した上で npx ejs コマンドを実行することで所望の結果を得ることができます。

ターミナル
# EJSの導入
npm install --save-dev ejs

# EJSの実行
npx ejs src/source.ejs -o dist/target.html

EJSを単体で利用したい場合にはこの方法でも十分ですが、その他にも様々な処理を一挙に行いたい場合にはWebpackを利用すると便利です。一方で、様々な処理が可能なWebpackはその分だけ学習コストが高いという側面もあります。プロジェクトの開発環境やコスト等を考慮しながら導入を検討すると良いと思います。

後書き

サンプルコード
/website/website-dev-on-webpack5/ejs-on-webpack5

  1. 実際には、GitHubのWebサイトでは各ページのコンテンツが動的に生成されていると思いますが、ここではそういったコンテンツが事前に用意できるような場合を考えていると思ってください。

  2. 一般に「生の」というフレーズは「無加工の」「比較的低レベルの」というような意味で使用されますが、ここでは「Webサイトに直接アップロードするそのままの」というような意味も含んでいます。実装するソースファイルの内容は必ずしもWebサイトにアップロードして公開するHTML/CSS/JavaScriptファイルと同一でなくても良いので、実装の際にはより便利な記法やプログラミング言語を使用できると嬉しいという気持ちが暗に込められています。

  3. ここで紹介したフレームワークには「HTMLファイルを静的に生成する」ためのツールがあるらしく、HTMLテンプレートエンジンと同様の使い方ができるかもしれません(詳細はあまり把握していません)。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?