Hypernova/Webpacker/Turbolinks でSSRできてSPA風に動くスケルトンを作った

  • 2
    Like
  • 0
    Comment

https://github.com/mizchi-sandbox/packnova

対象

  • Rails だけどSPAっぽく画面遷移したい
  • SEO担保しないといけない
  • 新規設計の参考

jQuery まみれの状態からこれと同等のことをするのは、不可能じゃないけど難しいです。

単にどう導入するか知りたいだけなら https://github.com/mizchi-sandbox/packnova/commit/447a91ea3a706c0bb0aac8570d1fbbaf6c9710f1 のコミットで

目指したモノ

最小限の設定で Rails エンジニアでもメンテ出来るSSR/SPAアプリの土台。
ただし土台をハックし始めるとその限りではない。。

スタック

  • webpacker でコンパイル
  • 画面遷移は hypernova-react/turbolinks で自動再マウント

ルーティングはReact側に寄せてます。なので react-router は入ってないです。
入れる選択肢もありますが、 react-router のSSRはとにかくだるいので、複雑さでメンテできなくなるのを考慮しました。代わりに turbolinks を引っ張り出しました。なのでオープンリダイレクタに気をつける必要があります。

シンプルさを優先してReduxは載ってないです。

どんな書き味か

app/views/home/index.html.erb
<%= render_react_component('Header') %>
<%= render_react_component('App', name: 'Hypernova') %>
app/views/about/index.html.erb
<%= render_react_component('Header') %>
<%= render_react_component('About') %>
app/javascript/exposeComponents.js
import { renderReact } from 'hypernova-react'
import _App from './components/App'
import _About from './components/About'
import _Header from './components/Header'

export const App = renderReact('App', _App)
export const About = renderReact('About', _About)
export const Header = renderReact('Header', _Header)

renderReact の登録名を手がかりに、 rails のヘルパが引き直して render という感じ。

erbのヘルパの第二引数がルート要素への props になります。なので props の組み立ては Rails 側になります。API経由してガチャガチャやるよりこっちのがシュッとします。

画面切り替わり時は自動的にサーバーから降ってきたpropsを元に自動的に再render します。(警告が出ますが、React v16 で render => hydrate になったので、そのうち hypernova-react をアプデすれば直るでしょう)

実体としては script タグで json 埋め込んでそれを手がかりに評価してるという感じです。

SSR

rails s でそのまま起動してもSPAとしては動きますが、SSRはしません。SSRしたければ 3001 に hypernova プロスセスを立てる必要があります。

yarn babel-node node/hypernova.js

標準出力に attached だか connected だか出てればOKです。

問題は、デプロイ時にこのnodeプロセスも一緒に立てないといけないって点ですね… ここはもうちょっと手を入れたい。

省いたこと

  • webpacker についての詳細
  • turbolinks で気をつけるべき挙動

これらは自分で調べてください。