今回は、sendgrid-demoboxというデモアプリの紹介ついでに、最近行なった更新内容についてつらつらと書いていこうと思います。
この記事はSendGrid Advent Calendar 2016の8日目の投稿です。
飲み会の帰り道は決まって納豆巻きを購入する佐藤です。二日酔い防止に効くかどうかは知りません。
きっかけ
このWebアプリケーションは、SendGridのデモ用に作成・公開しているものです。初期バージョンは2年前にコミットしたものが最後でしたが、あれから時間が経過してコードベースも古くなってしまっていました。Web API v3対応後のSendGrid公式ライブラリもまだまだ未成熟ながらだいぶ動くようになってきたのと、相変わらず変化の激しいJavaScript周りの新しい技術に触れるのにちょうどいい機会だと感じたので、全体的に実装し直そうと思い立ちました。
今回の目標
今回、目標とした更新内容は次の通りです。
- クライアント周りをReact+Fluxで構成する
- Web API v3のメール送信エンドポイントの全パラメータに対応する
- SendGrid公式ライブラリを使ってWeb APIにアクセスする
sendgrid-demoboxの概要
このアプリには次の機能があります。
- アプリ起動時にWeb API経由でSendGridを自動設定
- Web APIによるメール送信
- Event WebhookのPOSTを受信してWeb Socket経由で画面にリアルタイム表示
- Parse WebhookのPOSTを受信してWeb Socket経由で画面にリアルタイム表示
Reactの雛形を使うと自然とサーバサイドはNode.jsになると思いますが、SinatraとRubyが好きなので敢えてSinatraにしました。
画面イメージ
Webアプリ(Sinatra)起動後、サイトのトップページにアクセスすると以下のような画面が表示されます。
-
メールを送る
画面左側でメール送信用のパラメータを指定して送信ボタンを選択すると、Web API v3経由でメールが送信され、Event Webhookで受け取ったイベントが画面右側にリアルタイムに表示されます。
-
メールを受ける
画面上部に表示されている受信用アドレス(Mailto:〜部分)にメールを送信すると、Parse Webhook機能によりPOSTされた内容が画面にリアルタイム表示されます。
成果
-
クライアント周りをReact+Fluxで構成する
- 以前のバージョンはjQueryとerbによる伝統的な実装でしたが、新しいバージョンではReactとFluxxorを組み合わせた実装に生まれ変わりました。ほとんどがWeb API v3のメール送信エンドポイントのパラメータ入力ための実装です。このエンドポイントはパラメータ数が非常に多いのですが、似たような入力部分のコンポーネント化にReactが威力を発揮してくれました。
- Fluxアーキテクチャにより、画面から入力されたデータの保持と送信をAction、Dispatcher、Storeにそれぞれ分離してSinatraにPOSTする、という流れがわりとスッキリいったのではないかと思います。
- Webhookの受信をトリガとした画面のリアルタイム更新にSinatra RocketIOというRubyベースのWeb Socket/Cometライブラリを使用しました。FluxでWeb Socketのイベントをどこに流し込むか問題は橋本商会さんの記事が非常に参考になりました。
- 実装を始めた当初は意識していなかったのですが、Reactのアニメーションは思いのほか書きにくかったです。以前は1行のjQuery呼び出しで済んでいた実装が、React標準の方法だと「CSSをいじって、CSSTransitionGroupタグで括って...」とかめんどくさくてキレそうになったので、今回はreact-flip-moveというのを使用しました。やりたいことが全部できました。素晴らしい。
- ただ、クライアントサイドのコード量は前に比べて爆発的に増えました。
-
Web API v3のメール送信エンドポイントの全パラメータに対応する
コード量が爆発的に増えたのはWeb API v3のメール送信エンドポイントのパラメータ数の多さが主な原因です(Reactにもちょっとだけ原因がありますが)。単一の宛先に1通メールを送るだけだとちょっと複雑に感じますが、宛先毎の本文への文字差し込みや、メールの識別用にヘッダへ特殊なキーを入れたりと様々なユースケースに対応できる柔軟性の高いエンドポイントではないかと思います。 -
SendGrid公式ライブラリを使ってWeb APIにアクセスする
SendGridのWeb APIへのアクセスはサーバサイド(Sinatra)から行なっています。アプリ起動時にSendGridのEvent Webhook、Parse Webhook、Transactional Templateの各機能をWeb APIで自動的に設定し、メール送信時にはReact側で構築したリクエストボディを一旦サーバサイドを経由してSendGridのWeb APIを叩いています。これら全てにSendGrid公式ライブラリを使っています。クライアント(ブラウザ)からWeb APIを直接叩いていないのはCORS関連の問題のためです。解決には時間がかかりそうな雰囲気。
今後の課題
今回のアップデートで課題に感じたことは次の通りです。
-
Reactコンポーネントのテスト
結果的に今回はReactコンポーネントのテストを省略しました。理由としては、Node.jsを利用していないので、ブラウザ上でテストすべきだろうと思うのですが、一番王道っぽいJestがブラウザ上のテストをサポートする気がなさそうで、まだまだ流動的と感じたためです。現時点ではSinatraは使わずにNode.js+Expressあたりにしておくのが長いものに巻かれる意味では色々楽そうです。JestのSnapshot Testingには感動しました。まさに「Painless JavaScript Testing」。是非使ってみたい機能です。 -
JavaScript周り
JavaScriptのプロジェクトを新規作成するのは2年ぶりとかいう浦島太郎状態なので、ReactやFluxの他、Babel、ES2015、Jest、Mochaなどいろいろと勉強になりました。また、相変わらずこの辺りは混沌としていている雰囲気も感じ取れました。今回は、ビルドにGruntとWebpackを利用しましたが、調べた限りではもうちょっとトレンディーなツールはありそうです。いろんなツールの位置関係やトレンドを把握しつつゴチャゴチャと組み合わせないといけないのがいつも憂鬱楽しいです。
最後に
はじめはReactとSendGridのWeb API v3の導入が主目的だったのですが、実際作業を始めてみると、ほとんどの時間はJavaScript周りで利用するツールの調査に費やされてしまいました。
React+Fluxに関して言えば、以前より実装が整理されてメンテナンス性は断然向上していると思います。これは、アプリケーションの規模が大きくなったときにより効果を発揮すると思います。今回は軽いノリでやれましたが、jQuery+erbをReact+Fluxに書き直すのはクライアントサイドを全部捨てる覚悟がいるので、運用中のサービスでやるのはいろいろなものを天秤にかけて判断が必要なところじゃないかと思います。
今回イマイチだった部分は継続して改善していこうと思います。