LaravelでReact/VueをSSRする

PHP

ReactやVueのサーバーサイドレンダリングといえばExpressなどを使ってNode.jsベースでやるのが一般的かと思います。LaravelでSSRまでカバーしようとすれば、通常は回りくどいやり方が必要になるのでハードルが上がってしまいます。
ですがこのたびlaravel-server-side-renderingを試してみたところ、とても簡単にSSRが実現できてしまいました。JavaScript処理系としてPHP拡張のV8Jsを使った場合や、Windowsでの実行も試してたので、導入の簡単な流れと、そこでわかったことをまとめてみます。

Laravelを準備

$ composer create-project --prefer-dist laravel/laravel ssr-app "5.5.*"
$ cd ssr-app
$ php artisan preset react    // Reactを使う場合
$ npm install

など。詳細は割愛。

SSR用のComposerパッケージを導入

先述の通りspatie/laravel-server-side-renderingを使用します。このパッケージはspatie/server-side-renderingのLaravel向けラッパーで、React-Router使用時のLocation指定などもよしなにやってくれます。

$ composer require spatie/laravel-server-side-rendering

laravel-server-side-renderingの設定

設定ファイルを書き出します。

$ php artisan vendor:publish --provider="Spatie\Ssr\SsrServiceProvider" --tag="config"

config/ssr.phpに設定ファイルが作成されます。設定ファイルはデフォルトでNode.jsを使うようになっているので、V8Jsを使う場合には次のように変更します。

// @file config/ssr.php
- 'engine' => \Spatie\Ssr\Engines\Node::class,
+ 'engine' => \Spatie\Ssr\Engines\V8::class,

Node.jsとV8Jsについて

laravel-server-side-renderingではサーバーサイドのJavaScriptの実行環境としてNode.jsとV8Jsを使うことができます。それぞれの注意すべき点として、

Node.jsでは、

  • Node.jsが必要
  • WindowsのNode.exeではエラーが出る($ php artisan serveが開発環境として使えない。WSLのNodeなら動く

V8Jsでは、

  • ビルドが面倒(Ubuntuではaptとpeclを使ってインストールが可能。WindowsにはV8Js拡張込みのバイナリが配布されている)
  • JavaScriptのコードによっては動かない(V8JsにはsetTimeout()などが無かったり

などがあります。WindowsのNode.exeで動作しないのは私の環境が悪い可能性もあるので、念のため皆様の方でもご検証いただければと思います。

V8JsはWindowsでもそのまま動いてくれてありがたいのですが、MobXなどを使っているとsetTimeout()が無い! と怒られてしまいました。

アプリケーションの作成

laravel-server-side-renderingのREADMEのほか、React/Vueを使ったサンプルなどを参考に作成します。動作確認だけなら手っ取り早くサンプルをcloneしちゃいましょう(.envは別に用意)。

完成したらReact/Vueのビルドを忘れずに。

$ npm run dev

など。

SSRの確認

環境変数のAPP_ENVをproductionにするとSSRが有効になります。

APP_ENV=production

ブラウザの開発ツールなどでJavaScriptを無効にしてもページがレンダリングされることを確認します。

Laravel SSR

まとめ

JavaScriptの処理系についてはそれぞれ制限があったりするので、開発環境ではV8Jsを使い、本番環境ではNode.jsを使うといったような使い方をするのも良い思います。

この手法はNext.jsのようなお手軽Code Splittingのような事はできませんが、Laravelで完結するアプリケーションを作るならSSRの選択肢の一つとして考えてみてもいいのではないでしょうか。

コメント