このマニュアルはphp7.0のみに対応したものです。php7.1以上ではreactjs.htmlをご覧ください。

Redux UIチュートリアル

このチュートリアルではTwigテンプレートエンジン等の代わりにV8JsとRudux-ReactJsを使ってHTMLレンダリングします。 マルチエントリーの非SPAアプリケーションを主な対象としていてJavaScriptではルーターは使用していません。

既存のテンプレートエンジンを使ったWebアプリケーションから、ページ単位でRedux React UIを使ったアプリケーションに移行することができます。

前提条件

  • php7.0
  • V8Js
  • node
  • yarn

インストール

BEAR.Sundayプロジェクトを作成します。

composer create-project bear/skeleton MyVendor.MyRedux

vendor名をMyVendorproject名をMyReduxとして入力します。

次にBEAR.ReactJsModuleをインストールします。

cd MyVendor.MyRedux
composer require bear/reactjs-module ~0.3

Reduxのスケルトンアプリをインストールします。

cp -r vendor/bear/reactjs-module/ui-skeleton/redux/ui .
cp vendor/bear/reactjs-module/ui-skeleton/redux/package.json .
yarn install

Redux UIの作成

exampleからcpしてhelloページを作成します。

cp -r ui/src/page/example ui/src/page/hello

ui/entry.jsを変更します。

module.exports = {
  react: 'src/react-bundle.js',
  ssr_hello: 'src/page/hello/app/server',
  hello: [
    'webpack/hot/dev-server',
    'webpack-hot-middleware/client',
    'src/page/hello/app/client',
  ],
};

lintやtest、buildを試してみましょう。(必須ではありません)

yarn run lint
yarn run test
^C
yarn run build

src/Module/AppModule.phpにモジュールをインストールします。

<?php

namespace MyVendor\MyRedux\Module;

use BEAR\Package\PackageModule;
use BEAR\ReactJsModule\ReduxModule;
use BEAR\Package\AbstractAppModule;
use josegonzalez\Dotenv\Loader as Dotenv;

class AppModule extends AbstractAppModule
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        //configure()に追加
        $distDir = dirname(__DIR__, 2) . '/var/www/dist';
        $this->install(new ReduxModule($distDir, 'ssr_hello'));
        $this->install(new PackageModule);
    }
}

リソースの作成

既存のsrc/Resource/Page/Index.phpを変更します。リソースオブジェクトのレンダラーをRedux UIにするためにsetRendererセッターインジェクションに@Inject@Namedをアノテートします。@Namedの値はReduxModuleで指定したJSアプリケーションの名前と同じにします。

<?php

namespace MyVendor\MyRedux\Resource\Page;

use BEAR\Resource\RenderInterface;
use BEAR\Resource\ResourceObject;
use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;

class Index extends ResourceObject
{
    /**
     * @Inject
     * @Named("ssr_hello")
     */
    public function setRenderer(RenderInterface $renderer)
    {
        parent::setRenderer($renderer);
    }

    public function onGet($name = 'BEAR.Sunday')
    {
        $this->body = [
            'title' => 'To ' . $name,
            'hello' => ['message' => 'Hello ' . $name]
        ];

        return $this;
    }
}

テンプレートの作成

リソースのテンプレートsrc/Resource/Page/Index.html.php を作成します。

<?php
/* @var $ssr BEAR\ReactJsModule\Ssr */
list($markup, $script) = $ssr->render(['hello']);

return <<<"EOT"
<!doctype>
<html>
<head>
  <title>{$ssr->escape('title')}</title>
</head>
<body>
  <div id="root">{$markup}</div>
  <script src="build/react.bundle.js"></script>
  <script src="build/hello.bundle.js"></script>
  <script>{$script}</script>
</body>
</html>
EOT;

リソースオブジェクトからpreloadedStateとして使う値のキーだけを指定してrender()します。上記リソースからページのタイトルtitleReduxのpreloadedStatehelloを使用します。

実行

startコマンドを実行するとwebpackが実行され127.0.0.1:8080でWebサーバーが実行されます。

yarn run start

開発用にdevコマンドを実行するとphpcs/phpmd監視やHMRbrowserSyncの機能と共にstartが実行されます。 注) HMRはpure functionのコンポーネントには対応していないようです

yarn run dev

デバック

  • Chromeプラグイン React developer toolsRedux devToolsが利用できます。
  • {"title":"To BEAR.Sunday","message":"Hello BEAR.Sunday"}などとJSONが出力された場合はレンダラーのインジェクションが行われていなくて、Json Rendererが使用されています。
  • Unexpected key "{key}" found in preloadedStateの例外は存在しないResouceObject::$bodyのキーを指定していることを示しています。
  • 500エラーが帰ってくる場合はvar/logcurl にアクセスしてレスポンス詳細を見てみましょう

このチュートリアルで作成したアプリケーションはMyVendor.MyReduxで参照できます。

リファレンス