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テンプレートと{被(かぶ)るから(いや)だ」といっても我慢(がまん)してください。