JavascriptでHTMLメールを送(おく)る際(さい)のテンプレートを考(かんが)える(Pug、Handlebars、EJS)

テンプレートに何(なに)を使(つか)うか迷(まよ)ったので比較(ひかく)してみます。

送(おく)りたいメール

<body>
Name さま<br>
いつも〇〇をご利用いただき、ありがとうございます。<br>
<br>
Name さまが現在保有しているポイントは、 ### ポイントです。<br>
うち ## ポイントが今月末に失効になります。<br>
<br>
詳しくは<a href="Url">こちら</a>からご確認ください。
</body>

やりたいことは、

  • Name、###、##、Urlを動的(どうてき)に変更(へんこう)したい
  • 失効予定(しっこうよてい)のポイントがない場合(ばあい)は「うち ## ポイントが〜」の文(ぶん)自体(じたい)をなくしたい

こんな感(かん)じです。

Pugの場合(ばあい)

template.pug

body
  | #{name} さま
  br
  | いつも〇〇をご利用いただき、ありがとうございます。
  br
  br
  | #{name} さまが現在保有しているポイントは、 #{current} ポイントです。
  br
  if lost
    | うち #{lost} ポイントが今月末に失効になります。
    br
  br
  | 詳しくは
  a(href=url) こちら
  | からご確認ください。

コンパイル

const pug = require('pug');

const html = pug.renderFile('template.pug', {
    name: 'hoge',
    current: 100,
    lost: 10,
    url: 'https://blare.fwhy.app'
});

結果(けっか)

<body>hoge さま<br/>いつも〇〇をご利用いただき、ありがとうございます。<br/><br/>hoge さまが現在保有しているポイントは、 100 ポイントです。<br/>うち 10 ポイントが今月末に失効になります。<br/><br/>詳しくは<a href="https://blare.fwhy.app">こちら</a>からご確認ください。</body>

Handlebarsの場合(ばあい)

template.hbs

<body>
    {{name}} さま<br>
    いつも〇〇をご利用いただき、ありがとうございます。<br>
    <br>
    {{name}} さまが現在保有しているポイントは、 {{current}} ポイントです。<br>
    {{#if lost}}
    うち {{lost}} ポイントが今月末に失効になります。<br>
    {{/if}}
    <br>
    詳しくは<a href="{{url}}">こちら</a>からご確認ください。
</body>

コンパイル

const fs = require('fs');
const Handlebars = require('handlebars');

const html = Handlebars.compile(fs.readFileSync('template.hbs', 'utf-8'))({
    name: 'hoge',
    current: 100,
    lost: 10,
    url: 'https://blare.fwhy.app'
});

結果(けっか)

<body>
    hoge さま<br>
    いつも〇〇をご利用いただき、ありがとうございます。<br>
    <br>
    hoge さまが現在保有しているポイントは、 100 ポイントです。<br>
    うち 10 ポイントが今月末に失効になります。<br>
    <br>
    詳しくは<a href="https://blare.fwhy.app">こちら</a>からご確認ください。
</body>

EJSの場合(ばあい)

template.ejs

<body>
    <%= name %> さま<br>
    いつも〇〇をご利用いただき、ありがとうございます。<br>
    <br>
    <%= name %> さまが現在保有しているポイントは、 <%= current %> ポイントです。<br>
    <% if (lost) { -%>
    うち <%= lost %> ポイントが今月末に失効になります。<br>
    <% } %>
    <br>
    詳しくは<a href="<%= url %>">こちら</a>からご確認ください。
</body>

コンパイル

const ejs = require('ejs');

const html = await ejs.renderFile('template.ejs', {
    name: 'hoge',
    current: 100,
    lost: 10,
    url: 'https://blare.fwhy.app'
});

結果(けっか)

<body>
    hoge さま<br>
    いつも〇〇をご利用いただき、ありがとうございます。<br>
    <br>
    hoge さまが現在保有しているポイントは、 100 ポイントです。<br>
    うち 10 ポイントが今月末に失効になります。<br>
    <br>
    詳しくは<a href="https://blare.fwhy.app">こちら</a>からご確認ください。
</body>

総評(そうひょう)

Pugはコンパイル結果(けっか)に改行(かいぎょう)が含(ふく)まれていないので多少(たしょう)はメール容量(ようりょう)の削減(さくげん)ができそうです。
が、いかんせんテンプレートを書(か)くのが面倒(めんどう)すぎます。
Vue.jsで使用(しよう)するときみたいに全行(ぜんぎょう)を<div>や<p>タグで囲(かこ)むようにすればよいのでしょうが、 今回(こんかい)のように<body>に平文(ひらぶん)で書(か)きつつ改行(かいぎょう)は適宜(てきぎ)<br>で行(おこな)うような場合(ばあい)には不向(ふむ)きなようです。

HandlebarsとEJSはテンプレートも出力(しゅつりょく)されるHTMLもさほど変(か)わりないですが、結論(けつろん)から言(い)うとEJSのほうが良(よ)さそうです。
上記(じょうき)の例(れい)には出(だ)しませんでしたがHandlebarsは別(べつ)ファイルの取(と)り込(こ)みが苦手(にがて)なようです(できなくはないようですが)。
他(ほか)のメールも送(おく)る場合(ばあい)、署名等(しょめいとう)の共通(きょうつう)な箇所(かしょ)は別(べつ)ファイルにしたくなると思(おも)うので、簡単(かんたん)に取(と)り込(こ)みできるEJSのほが良(よ)いと思(おも)います。
またメール送信(そうしん)にSendGridを使(つか)う場合(ばあい)、SendGrid側(がわ)のテンプレートがHandlebarsの構文(こうぶん)と被(かぶ)るのでEJSのほうが楽(らく)です。

あと、人によっては「<% %>は通常(つうじょう)のHTMLタグと被(かぶ)るのが嫌(いや)だ」というのがあるかもしれませんが、安心(あんしん)してください変更(へんこう)できます。 Handlebarsは変更(へんこう)できないので「{ }}がLaravelのBladeテンプレートと{被(かぶ)るから嫌(いや)だ」といっても我慢(がまん)してください。