React.jsのserver-side レンダリングを試す
React.js Tutorialではフロントエンドでの実例が用いられていた。
githubリポジトリ上には、React.jsを使ってDOM(Virtual DOM)をサーバサイド側で構築し、
フロントエンド側にはレンダリング結果を返す、というサンプルがある。
このサンプルを試用して
react-bootstrapを使ったりGrunt 使ったりして
自分なりにReact.jsでのserver-sideレンダリングに対する理解を深めるため
コードを書いてみよっかなと思った。
以下記録。
まずreact-server-exampleを試す
をgit cloneし、動作確認をしてみた。
プロジェクトソースを手元に持ってくる
> git clone git@github.com:mhart/react-server-example.git
必要なパッケージのインストール
> cd react-server-example
> npm install
react-server-exampleを起動してみる
react-server-exampleのディレクトリ以下で、
server.jsを起動する
> node server.js
Listening on 3000…
ブラウザでアクセスしてみる
> open http://localhost:3000/
おお、レンダリングされてる。
var props = {items: [0, 1, '</script>', '<!--inject!-->’]}
の内容がレンダリングされている。なるほど。
react-bootstrapを使ったサンプルを書いてみる
react-bootstrapというものをreact componentsで見つけたので、
react-server-exampleのコードを元にreact-bootstrapを使うサンプルを書いてみた。
サンプルのリポジトリ
react-server-bootstrap-example
サンプルの動かし方
githubリポジトリをcloneし、npm installし、
node server.jsで立ち上げる
> git clone git@github.com:futoase/react-server-bootstrap-example.git
> cd react-server-bootstrap-example
> npm install
> node server.js
サーバが立ち上がった後、**http://localhost:3000**をブラウザで開く
> open http://localhost:3000
react-server-bootstrap-exampleをどう構成しているか
ディレクトリツリー
こんな感じ。
.
├── Gruntfile.js
├── LICENSE-MIT
├── README.md
├── dest
│ └── app.js
├── npm-debug.log
├── package.json
├── server.js
├── src
│ ├── jumbotron.js
│ ├── main.js
│ ├── page.js
│ └── tab.js
└── templates
├── index.ect
└── layout.ect
React.js以外で使ったもの
grunt
grunt-reactを使うために利用した。
> grunt
このコマンド一発で、複数のJSXファイルが一つのjsファイル(src/app.js)にまとめられる。
ファイルの変更を見てるだけだけど。(単体ファイルならreact-toolsでもできる)
- ソースファイルの結合
JSXファイルを[srcディレクトリ以下[(https://github.com/futoase/react-server-bootstrap-example/tree/master/src)に書いているのだけど、
jsxコマンド(react-tools)で作るのではなく、grunt使ってdest/*.jsをsrc/app.jsに結合するようにした。
ECT
爆速テンプレートエンジンという。サーバサイド側がレンダリングするフロントエンド側の
テンプレートを出力するために使った。もともと参考にしていたreact-server-exampleでは
文字列結合をしていたため。
browserify
参考にしていたreact-server-exampleから。
browserifyについてあんましっかりとした認識はなかったが、
サーバサイドでレンダリングしたJSに対しrequire文を使って
node.js側で生成したjsのモジュールをフロントエンド側に渡せるんだなというのが良い。
/dest/bundle.jsにアクセスすると、
/dest/app.jsとしてJSXから変換されたjsファイルを取り込んだ形で
フロントエンド側に提供することができる。よく出来てるなあ...
literalify
browserify-transform-toolsを利用したもののようだ。
literalifyそのものは、src/app.jsのrequire('react')をwindow.Reactに置き換える。
以下に比較できるソースコードを貼る。
var React = require('react');
module.exports = React.createClass({displayName: 'exports',
render: function() {
return (
React.createElement("div", {className: "container"},
React.createElement(JumbotronBox, null),
React.createElement(TabbedAreaBox, null),
React.createElement(PageHeaderTitle, null),
React.createElement(PageMessage, null)
)
);
}
});
var React = window.React;
module.exports = React.createClass({displayName: 'exports',
render: function() {
return (
React.createElement("div", {className: "container"},
React.createElement(JumbotronBox, null),
React.createElement(TabbedAreaBox, null),
React.createElement(PageHeaderTitle, null),
React.createElement(PageMessage, null)
)
);
}
});
window.Reactはどっから来るんだろっていうのは、facebookのReact.js用のCDNにより、定義されている。
var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.React=e()}}(function(){return function e(t,n,r){function o(i,s){if(!n[i]){if(!t[i]){var u="function"==typeof require&&require;if(!s&&u)return u(i,!0);if(a)return a(i,!0);var c=new Error("Cannot find module '"+i+"'");
"undefined"!=typeof window?t=window
によって、window.React(t.React)が定義されている。
話がずれるけど
browserifyすごいなぁ。サーバサイドレンダリング側とフロントエンド側の
オブジェクトを糊でくっつける感じだ。
list-of-transformsに書かれているプロダクトリポジトリを見て回って面白かった。
React.jsのserver-sideレンダリングを試してみて
React.jsのserver-sideレンダリングを試して、
面白いなと思った。
また、browserifyについて触ってなかったので
どういったものなのかが知見が得られた。面白いなあ。
こういうのがどんどん出てくるので楽しい。