メールの HTML を React + TypeScript + TailwindCSS で書く
React コンポーネントをサーバーサイドレンダリングすることで、メールの HTML を React で書くことができる。
フロントエンドで React を使っている場合、一貫性のある技術スタックになって嬉しい。また TypeScript であれば型安全にメールがかけるので、なお嬉しい。
基本的には、下記のようにすれば、静的な HTML が吐き出せる。これを Mailgun などに送れば OK。
import React from 'react'
import ReactDOMServer from 'react-dom/server'
const Email = () => (
<html>
<body>
<div>
<p>Hello, email!</p>
</div>
</body>
</html>
)
const html = ReactDOMServer.renderToStaticMarkup(element)
CSS は <head />
の中に書いてしまうのが一番簡単。また Juice を使ってインライン化すれば、 Outlook などにも対応しやすい。
import juice from 'juice'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
const Email = () => (
<html>
<head>
<style>{`
.button {
padding: 4px;
background-color: #333;
color: #fff;
}
`}</style>
</head>
<body>
<div>
<p>Hello, email!</p>
<button className="button">LEARN MORE</button>
</div>
</body>
</html>
)
const staticMarkup = ReactDOMServer.renderToStaticMarkup(element)
const html = juice(staticMarkup)
このままでも良いのだが、 TailwindCSS をフロントエンドで使っている場合、同じ要領で書けると更に嬉しい。単純に <style>
内に TailwindCSS を全て入れても良いのだが、せっかくなので tailwind-rn
というライブラリを使ってみた。
もともとは React Native 用のライブラリだが、やっていることは TailwindCSS のクラスを React が扱える style
のオブジェクトに変換しているだけなので、いい感じに使える。普通に React Native で TailwindCSS 使いたい時にもお薦め。
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import tailwind from 'tailwind-rn'
const Email = () => (
<html>
<body>
<div>
<p>Hello, email!</p>
<button style={tailwind('p-1 bg-gray-800 text-white')}>
LEARN MORE
</button>
</div>
</body>
</html>
)
const html = ReactDOMServer.renderToStaticMarkup(element)
tailwind-rn
はインラインで CSS を記述するようになるので、 TailwindCSS で完結させれば Juice が必要なくなったのも嬉しい。
注意点としては text-lg
等のスタイルを利用すると、 line-height
がおかしなことになる。結局 Juice
でグローバルに * { line-height: 1.6 !important }
というスタイルを当てているが、もっと良い解決策がありそう。単位を必ず px
にするとか。