2015年3月17日
【翻訳】AngularJSからReactへ: Isomorphicな方法
(2014-09-08)by Péter Márton
本記事は、原著者の許諾のもとに翻訳・掲載しております。
本エントリは翻訳リクエストより投稿いただきました。
ありがとうございます!リクエストまだまだお待ちしております!
先週、私たちはWebサイトを検索エンジン向けにインデックス付けできるようにしようとしていました。この記事では、私たちがWebサイトを書き直していて学んだことの要約を紹介したいと思います。
背景
2ヵ月前に RisingStack.com を作成した時、私たちはそのWebサイトでどんなテクノロジを使うか決めなくてはなりませんでした。イベントを追跡する静的なページが数ページあるだけだったので、とても簡単でしたが、私たちはWebサイトをスケーラブルでできるだけ高速なままにしておきたいと考えていました。
私たちのチームは AngularJS の経験が豊富なので、フロントエンドにAngularを選ぶのは妥当だと思われました。
この記事はReactやAngularJSがどちらか一方より優れている理由について述べているわけではないので注意してください。どちらがいいかは常にユースケース次第です。
“Angularな方法”
AngularJSはGoogleによって開発されているかなりすごいツールです。ルーティングや双方向データバインディングのようなすばらしい機能をたくさん提供して、開発を勢いづけ、テスト可能なアプリケーションを作り出しています。
Angularによって単一ページアプリケーション(SPA)を作成することができ、コンテンツをクライアント側でレンダリングできますが、JavaScriptをサポートしない検索ロボットはコンテンツにインデックスを付けることができません。
それはSEOの観点から深刻な問題になる可能性があります。特に新しく設立されたNode.js企業を有名にしたい時はね(^-^)
JavaScriptを使用していない私たちのAngularサイト
koa-prerender
RisingStackでは、私たちは半端なことは好きではないので、この問題を解決したいと考えました。そんな時に登場したのが prerender.io です。ヘッドレスブラウザを使って外部サーバ上にサイトをレンダリングし、その結果をHTMLで送り返してくれる外部サービスです(オープンソースプロジェクトでもあります)。
それにより、ほとんどの検索エンジンが読み取り可能なサイトになりますが、AngularJSバインディングが解かれてしまうので本物の人間のユーザのためにprerender.ioを使うことはできません。
私たちのサイトでは、ジェネレータをベースとした、prerender.ioにサポートされていないNode.jsフレームワークである Koa が使われているので、私たちはprerender.ioを自分たちで実装しなければなりませんでした。
それでRisingStackはKoa向けの koa-prerender ミドルウェアを公開しました。
簡単に言うと、リクエストパラメータ( _escaped_fragment_
やuser-agentなど)からクローラを検出し、外部のprerenderサービスを呼び出して静的なHTMLコンテンツで応答します。
ようやくGoogleやYahooのような検索エンジンのほとんどにサイトを見つけてもらえるようになったので私たちは喜びましたが、それで終わりではありませんでした。ユーザエージェントは変わる可能性がありますし、同じユーザエージェントのままにしておきたくはないので、私たちはより良いソリューションを探し続けました。
JavaScriptを使用していないがkoa-prerenderを使用している私たちのAngularサイト
IsomorphicなJavaScript
私たちが求めていたのは、最初にロードした時はサーバサイドでコンテンツをレンダリングするが、その後はシングルページアプリケーションとしての体験を提供するものです。
クライアントサイドとサーバサイドの両方でレンダリングすることができ、2つのサイドの間でアプリケーションの状態を共有できるものが必要でした。そうすれば、クライアントは、サーバがジョブを終えたポイントから続行できるはずです。
この種のアーキテクチャを実装するためには、コードベースがサーバサイドとクライアントサイドで共通でなければならず(BrowserifyまたはWebpack)、またアプリケーションも両方のサイドでレンダリングできなければなりません。
「Browserifyでは、従属関係をすべてまとめることにより、ブラウザ内でrequire(‘modules’)ができるようになります」 – browserify.org
このことは、事実上、Node.jsの従属関係システムと npm パッケージをブラウザ内で使用できるということを意味します。例えば、AJAXリクエストのための superagent や、フローコントロールを改善するための async などです。
IsomorphicなJavaScript アーキテクチャ 出典: AirBnb Nerds
isomorphicなアプリケーションの詳細については、ぜひAirBnbの記事を参照してください: Isomorphic JavaScript: The Future of Web Apps
React
ユーザインタフェースを構築するためのJavaScriptライブラリ – React
React は、データバインディングに単方向のフローを使用してクライアントサイドとサーバサイドの高性能なレンダリングを提供します。ReactJSはオープンソースで、Facebook Engineeringチームにより構築されました。
Reactはフレームワークではないので、Facebookの Flux アプリケーションアーキテクチャのような他のソリューションを使って拡張します。
Fluxについて
「FluxはMVCを避けて単方向データフローを採用します。ユーザがReactビューと対話すると、このビューはセントラルディスパッチャを介して、アプリケーションのデータとビジネスロジックを保存する様々な記憶装置にアクションを伝え、このアクションは、影響を受けるすべてのビューを更新します。このことは、状態間でビューをどのように推移させるかを指定することなく記憶装置がアップデートの保存と送信を行うことが可能な、Reactの宣言型プログラミングスタイルでは特に効果的です」 – Flux docs
Fluxアーキテクチャ 出典: http://facebook.github.io/
React + Flux + Koa = isomporhicの美点
ReactとFluxを使ってisomorphicなアプリケーションを作成すると決めてから、私たちは、他社からアイデア、つまりサンプルを探し始めました。
最終的には、Yahooの flux-examples を元にしてサイトの構築を開始しました。
Yahooのflux-examplesには、ルーティングと Express を使ったNode.jsの2つのisomorphicなアプリケーションのサンプルコードがありました。
このアイデアはとてもシンプルです。 Webpack を使えば、サーバサイドとクライアントサイドの両方から実行可能なJavaScriptコードを書けるということです(私たちはWebpackから Browserify に変えてしまいましたが)。
Isomorphicなアーキテクチャの主なコンセプトは以下のとおりです。
アプリケーションの状態とコードは、ブラウザとサーバ間で共有されています。サーバがリクエストを受け取ると、新しいflux-reactアプリケーションインスタンスを生成してレンダリングをします。すると、ストレージ(アプリケーション)の状態がそのレンダリング済みのHTMLアウトプットに渡されます:
サーバはこのレンダリング済みのファイルで応答します。
ブラウザは(BrowserifyやWebpackで作られた)同じコードをロードし、(サーバによって共有され、グローバル/ウィンドウスコープに送り込まれた)共有の状態からアプリケーションを起動させます。つまり、アプリケーションはサーバが処理を終えたポイントからずっと動き続けることができるのです。
ユーザは以前と同じように最初のロードで完全にレンダリングされたサイトを見ることができますが、超高速のシングルページアプリとしてネットサーフィンを続けることもできるのです。
JavaScriptなしでサイトのコンテンツを閲覧できるので、検索エンジンはインデックスを付けることができます。
( RisingStack.com はKoaを使うので、私たちはいくつかのミドルウェアを移し変えなければなりませんでした。近日 RisingStack GitHub repository で発表する予定です)
JavaScriptを使用していない私たちのReactのサイト
結論
ここでの私たちにとって一番のプラスになったのは、インデックス可能なisomorphicなSPAがやっと使えるようになったことでしょう。これは私たちの最優先課題ではありませんでしたが、今や人間のユーザのためにもJavascriptなしで私たちのサイトが機能するようになったのです。
繰り返しになりますが、今回の記事の投稿の目的はReactがAngularJSより優れていると主張することではありません。ある部分ではReactが勝っているのは事実ですが、別の部分ではAngularJSより劣っている部分もあります。どちらがいいのかはユースケース次第でしょう。
また、この2つは共存することもできます。 ngReactGrid プロジェクトがいい例です。
今回はここまでです。Isomorphicの時代が今後、Web開発やNode.jsに何をもたらしてくれるのか、私たちはとても楽しみにしています。
もし類似の話題があれば、ぜひあなたのお話を聞かせてください。私たちのツイッターアカウントは @RisingStack です。
アップデート:
発表したばかりのisomorphicの例です。
- Node.js (Koa + MongoDB) API: https://github.com/brewfactory/BrewCore
- Reactのclient: https://github.com/brewfactory/BrewUI
- ワーキングデモ: https://brewcore-demo.herokuapp.com
アプリケーションの開発をお手伝いします
RisingStackでは JavaScriptの開発とコンサルティングサービスを行っています。 ご連絡お待ちしています!
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa