PHPでReact.jsのサーバサイドレンダリング


こんにちは。VirtualDOM Advent Calendar 15日目のdekokunです。

14日目は[tomato360](http://qiita.com/tomato360)さんの「React.jsのチュートリアルを触る」でした。


## 要約

JSで描画する内容を事前にサーバサイドレンダリングするようにすると嬉しい事がいろいろ増えますが(詳細：[React.jsとserver-side rendering](http://qiita.com/koba04/items/a62a30c6934466ea8dea))、PHPでもできるようだったのでやってみました。というお話。

結論：react-php-v8jsはメンテされていない

## 使うライブラリ

- [react-php-v8js](https://github.com/reactjs/react-php-v8js)

## 使い方を簡単に

- 頑張って[V8Js PHP extension](http://php.net/v8js)をpeclでインストールする
	- そのためには頑張ってV8エンジンをインストールする必要がある。
- なお、私は上記もろもろが非常に厳しかったため、V8Js PHP extensionがインストール済みのDockerイメージを使用しました。[stesie / v8js](https://registry.hub.docker.com/u/stesie/v8js/)

## コード

以下参照

https://github.com/reactjs/react-php-v8js/blob/master/example/example.php

上記注意しなくてはいけないのは、react.jsのバージョンです。なんと、2014/12/20現在のreact-php-v8jsのmaster時点(といっても最終コミットは10ヶ月前)で、最新版の0.12で動かないのは当然(?)として、0.8.0じゃないと動きません。

イメージ的には以下の使い方です。

```PHP
<?php
$react = new ReactJS(
  file_get_contents('/path/to/react.js'), // react。バージョンは0.8.0で
  file_get_contents('/path/to/content.js') // 自分のアプリをconcatしたJS
);

// reactのrenderで指定するpropsを生成。
$data =
  array('data' => array(
    array(1, 2, 3),
    array(4, 5, 6)
  )
);

// 以下と同様のレンダリングを行えっていうことっぽい (reactのバージョン注意)
// React.renderComponent(Table({"data":[[1,2,3],[4,5,6]]}), document.getElementById("page"));
$react->setComponent('Table', $data);
?>

<!doctype html>
<html>
  <head>
    <title></title>
  </head>
  <body>

    <!-- getMarkupが、レンダリングされたHTMLを返している -->
    <!-- data-react-checksumも入っているため、それが正しければ再レンダリングは行われない -->
    <div id="page"><?php echo $react->getMarkup(); ?></div>

    <script src="react.js"></script>
    <script src="content.js"></script>

    <script>

    <!-- 以下JSが出力される なお、第二引数に文字列を渡すとその名前の変数に結果を代入するJSが出力される  -->
    <!-- React.renderComponent(Table({"data":[[1,2,3],[4,5,6]]}), document.getElementById("page")); -->
    <?php echo $react->getJS('#page'); ?>
    </script>
  </body>
</html>

```

メンテナンスがされていないせいでReact.render()というナウい書き方じゃなくてReact.renderComponent()だったりして趣深い

## react-php-v8jsの内部

クラスが1つあるだけです。`ReactJS::setComponent()`で、component名、及びpropsを`json_encode()`したものを内部に持ち、`ReactJS::getMarkup()`でV8Jsに対してReact.renderComponentToString()を渡してあげて出力をそのまま返している

中が非常にシンプルな作りであるため、新しいReact.jsで使いたい場合でも簡単に対応できますね。

## 最後に

今日は2014/12/20です。15日目のアドベントカレンダーを今日書いています。

実は一度[(草稿)JS弱者がBackboneでアプリ書いてて思った「VirtualDOMだったらここがよくなるだろうな」ってことを、ここの識者たちに「この理解でいいの？」って聞きたい](http://qiita.com/dekokun/items/c98cd1a98f5a1f12a6ef)というのを書いていたのですが、インフルエンザですごく適当なものを世に出してしまい、どうせならもうちょっとまともな別の記事書くかってなって慌ててPHPでサーバサイドレンダリング調べました。

PHPならJS弱者の私でも楽勝だぜ！！！って思いましたが、まずV8Js PHP extensionのインストールに死ぬほどもがき苦しみ、諦めてdocker使おうとしたけどdockerに慣れておらずもがき苦しみ、reactのバージョンも最新では動かず少しずつバージョンを落としながら試してみたりして結構地獄感ありました。

なお、現状、V8Js PHP extensionをCentOSで動かす方法が見つけられていません。世の中、難しいもんですねと思いました。

<blockquote class="twitter-tweet" lang="ja"><p>現在、一体誰の得になるのかもよくわからないことをするためにV8エンジンを単独でcompileしている。</p>&mdash; でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/545561016352776192">2014, 12月 18</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


V8エンジンをcompileしようとして死にそうになっているところ

<blockquote class="twitter-tweet" lang="ja"><p>svn checkoutの煉獄に身を焼かれる…</p>&mdash; でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/545568619107581952">2014, 12月 18</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>ゆとりなんでyumで入ってくれないと困るっていうか…</p>&mdash; でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/545570854877163521">2014, 12月 18</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>失敗に失敗を重ねており、うん、普通に公開されているdockerイメージを使おう！という感じでひとつ。</p>&mdash; でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/545581858679832576">2014, 12月 18</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>多分、この知識を必要としている人は世の中にほとんどいない。私も全く以って必要としていない。</p>&mdash; でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/546251115516264448">2014, 12月 20</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>