2016年11月2日水曜日

React-Reduxを使ったWebアプリをサーバサイドレンダリング(SSR)するには、こういう風にしたらいいんじゃないか的なお話

  • このエントリーをはてなブックマークに追加

React-Reduxを使った開発でのディレクトリ構成をどうしたらいいのか的なことから、こうやって組んだらいいんじゃないか的なお話ということで、前回つらつらと書いたわけだけど。
これはクライアント側のjs単体で動くわけだから細かいことを気にする必要がなかったからよかったが、SNSにシェアしたときにOGPが設定されないと困るわけで。
というのもfacebookやtwitterのbotがjsをレンダリングすることができないから。
ちなみにgoogleはちゃんとjsをレンダリングしてクローリングしてくれるからSEOとかは問題ないわけだけど、たまにSEOのためにSSRをしないとって言っている人がいるのは個人的に謎。

ということで今日はOGPに対応するためのサーバサイドレンダリング(SSR)をするにはこういう感じがいいよ的なお話をば。

とりあえずサンプルを作ったので、よかったらこちらのgithubからよろしくどうぞ。
今回は簡易的な例として作っておいた。
webpack/にwebpackの設定を、src/に必要なファイルを色々と。

ちなみにこのファイルの内容としては、meta(OGPとかtitleとか)をSSR時に設定をしつつ、ページ遷移をしたらtitleタグの中身を変えるとかそういう感じ。


■ざっくりとした流れ

・client.jsとserver.jsを作成する
・server.js内でapp.useとしてrouteにマッチしたら処理をする
・promiseを使って、全ての処理が完了したらhtmlをレンダリングする
・components/app.jsにて、componentDidMount時にdidMountフラグを立てる


■ポイント的なこと

細かく説明するとすごく面倒なので、ポイント的なものをいくつか。
・containersファイル内にfetchDataというstaticなメソッドを追加
・components/app.jsのcomponentDidMountでdidMountフラグ
・各componentのwillMountでdidMountフラグをチェックして処理

serverでレンダリングされた場合はcontainersのfetchDataでmetaをセットし、ページ遷移した場合はcomponentWillMountでmetaをセットする


■containersのファイル内にfetchDataというstaticなメソッドを追加する

componentsファイル内にstatic fetchDataとして記述してもよいのだが、
このfetchDataは基本的にserver.jsで呼び出すことを前提として考えているので、
あえてcontainers内に入れることによって処理が別だとわかりやすいんじゃないかと。


■components/app.jsのcomponentDidMountでdidMountフラグ

このapp.jsは全てのcomponentを包括するようにroute.jsで設定しているので、最後にdidMount処理が完了する。
なので最後のタイミングでdidMountフラグを立てることにより、各componentでcomponentWillMountが有効になる感じ。

またもし各componentのcomponentWillMountでdidMountフラグをチェックしないと、componentWillMountがserverでレンダリングされた場合と、ブラウザ側でレンダリングされた場合の二回呼び出されてしまうので要注意。


あまり今回はうまく説明ができないけど、とりあえずサーバサイドレンダリングをするにはこれをテンプレートとして使うと良さげ。
componentWillMountが二回呼び出されると多くの通信が発生してるってことで無駄だし。
正直なところOGPを気にしないのであれば、サーバサイドレンダリングを使わずブラウザ側のみでいいんじゃないかと。
というのもSEO的にはgoogleはちゃんとjsをレンダリングしてクローリングをするし、
読み込みが遅いかもしれない問題に関しては、適切なローディング表示を心がけてあげれば解消はできるわけで。

とりあえず説明もあまりうまくできないぐらいサーバサイドレンダリングは闇が深いよ的なみたいな。

Adsense