破いて捨てたノート

Webやテクノロジーやそれ以外に関する思いつき

Rails + React + ES6 のためのアセット環境構築

結論

Sprocketsの動作を維持しつつ、npmやgulpなどのモダンなパワーも取り入れた、いいとこどりな環境を構築してみた。

やりたいこと

  • SEOのため、Reactでserver-side renderingをしたい
  • JSコードをES6で記述したい
  • 既存のCoffeeScriptのコードも共存させたい(後ほど書き換える予定)
  • npmやgulpといったモダンな環境でアセット管理をしたい
  • browserifyを使いたい
  • Sprocketsが実現している機能は維持したい

そもそもSprocketsは何をしているか

周知のことでしょうが念のためおさらい。

  • ファイル毎の依存関係の管理
    • application.jsなどのマニュフェストファイルがやってること
  • altJSのコンパイル
  • アセットのminify
  • アセットの連結
  • アセットファイル名にMD5フィンガープリントを挿入

Sprocketsの問題点

  • JSライブラリをラップするgemに依存する
    • 使いたいライブラリがあるのにgemがないから使えないということが起きる
    • gemのメンテナンスが遅れ、古いバージョンのライブラリを使わざるを得なくなる
  • 似たようなgemが乱立していて混乱する
  • jadeテンプレートのようなものをbrowserifyなど使ってrequireして埋め込むとかできなくてツラい

Sprocketsのメリット

  • development環境の場合、アセットは個別のファイルとして、マニフェストファイルの記載順に読み込まれる
    • 元のJSファイルを参照しながら開発できる
  • あるファイルを弄った時は再読み込みをするだけでそのファイルだけ再コンパイルされて上手く更新してくれる
  • WebブラウザにキャッシュされたアセットファイルはMD5フィンガープリントが変更されることでいい感じに無効になる

サンプルアプリ

https://github.com/yachibit-sandbox/react_with_rails_and_gulp

ポイント

  • Server-side renderingをするためreact-railsを使用する

処理の流れ

  1. jsxはfrontend/javascripts配下にES6で記載していく(ディレクトリは仮)
  2. gulpとbabelでES6をES5にトランスパイルする
    • ファイルが変更されたら自動トランスパイルされるよう設定しておく
  3. 2.で生成されたjsをapp/assets/javascripts/componentsに配置する
  4. 3.で配置されたjsをsprocketsに読み込む
    • 読み込まれるようにマニュフェストファイル(application.js)を記載しておく

Deploy

だいたいこんな感じで動くと思います。

namespace :deploy do
  namespace :npm do
    task :install do
      # npm install
    end
  end

  namespace :assets do
    task :build do
      # npm run build
    end
  end

  before 'deploy:assets:precompile', 'deploy:assets:build'
  before 'deploy:assets:build', 'deploy:npm:install'
end

npmモジュールのreactではなくreact-railsを使用したのはなぜか?

react_component helperを使いたかったから。 通常、ReactでServer-side renderingをする際、renderToString(もしくはrenderToStaticMarkup)を使用して、ReactElementをHTML文字列として出力する。ここで出力されたHTML文字列を元に、サーバー側でviewを生成するが、JSの世界のHTML文字列をRailsのviewとしてうまい具合に表示させるのは面倒だった。react_component helperを使用すればそれが簡単に実現できるので、react-railsを使用することにした。

今後の展望

参考文献

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発