[Laravel] Reactのサーバーサイドレンダリング

PHPでのJavascriptのServer Side Renderringの方法としては、

  1. PHPで行う
  2. Node.jsなどでパースしたものを受け取る

のどちらかで実装しているみたい。

今回は1.のPHPで行ってみます。

便利そうなパッケージがあったので使います。

react-laravel

Composerでインストール

Installationの項目にある"minimum-stability": "dev"をcomposer.jsonへ追記してreact-laravelをインストール。

$ composer require talyssonoc/react-laravel
$ php artisan vendor:publish

config/app.phpReact\ReactServiceProviderのプロバイダーを追記します。

なお、PHPのExtenstionとしてv8jsが必要

NPMのインストール

Reactを利用するだけであれば必要なさそうでしたが、JSXを利用する為には1度コンパイルする必要があるので必要なものを入れます。

package.json

{
  "private": true,
  "devDependencies": {
    "gulp": "^3.8.8"
  },
  "dependencies": {
    "buble": "^0.12.5",
    "buble-loader": "^0.2.2",
    "laravel-elixir": "^6.0.0-9",
    "laravel-elixir-webpack-official": "^1.0.2",
    "react": "^15.3.0",
    "react-dom": "^15.3.0",
    "webpack": "^1.13.1"
  }
}
    $ npm install

gulpの設定

react-jsでのJavascriptの読み込みが、デフォルトではpublic/js/componentsなので、ここにJavascriptファイルがコンパイルされるよう追記します。

gulpfile.js

elixir(function(mix) {
    mix.sass('app.scss')
        .webpack('components.js');
});

コンポーネント作成

以下のファイルを作成してビルドします。

resources/js/components/WelcomeComponent.js

import React, { Component } from 'react';

class WelcomeComponent extends Component {
  constructor(props, context) {
    super(props, context);

    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    alert(this.props.title);
  }

  render() {
    return (
      <div classname="title" onclick="{this.handleClick}">{this.props.title}</div>
    );
  }
}

export default WelcomeComponent;

resources/js/components.js

import WelcomeComponent from './components/WelcomeComponent';

var glob = typeof window !== "undefined" ? window : global;

glob['Welcome'] = WelcomeComponent;

作成後にコンパイル

$ gulp

Bladeファイルの編集

resources/view/welcome.blade.php

<title>Laravel</title>
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css"><style>
    html, body {
        height: 100%;
    }

    body {
        margin: 0;
        padding: 0;
        width: 100%;
        display: table;
        font-weight: 100;
        font-family: 'Lato';
    }

    .container {
        text-align: center;
        display: table-cell;
        vertical-align: middle;
    }

    .content {
        text-align: center;
        display: inline-block;
    }

    .title {
        font-size: 96px;
    }
</style><div class="container">
    <div class="content">
        @react_component('Welcome', [ 'title' => 'Laravel 5' ])
    </div>
</div>

<script src="%7B%7B%20asset('vendor/react-laravel/react.js')%20%7D%7D"></script><script src="%7B%7B%20asset('vendor/react-laravel/react-dom.js')%20%7D%7D"></script><script src="%7B%7B%20asset('js/components.js')%20%7D%7D"></script><script src="%7B%7B%20asset('vendor/react-laravel/react_ujs.js')%20%7D%7D"></script>

動作確認

HTMLソース上に表示されました!

<div data-react-class="Welcome" data-react-props='{"title":"Laravel 5"}'><div class="title" data-reactid=".28w8vglweoy" data-react-checksum="-1540418249">Laravel 5</div></div>

また、見出し部分をクリックするとアラートが表示されることも確認。

© Xzxzyzyz