とりあえず現段階で幸せに慣れそうなRails 6.1の構成.md

3 min read読了の目安(約3300字 1

このファイルは何?

Railsでフロント書くのしんどいからreactとかvueとか入れたほうがいいんでしょ?

ってなった時にそれらを入れる前にやるべき事を書いたもの

めちゃくちゃ模索中なのでもっと良い構成を知っていたらむしろアドバイス求む

想定読者

  • 「フォローボタン」とか「いいね」とかを非同期ですっきり書ければそれで充分
  • 今はjqueryとかで無理やり頑張って書いてる

って人

(DHHが言ってるように世の中のアプリの9割以上はこれに当てはまってると思います

採用する技術

view component

これは全人類がmustで今すぐ入れたほうが良いので今回の話と関係なく導入しましょう

これが何か簡単に説明すると

= render partial: 'items/list'

Itemの一覧を表示したい時なんかに、こんな感じでrenderで別の場所から読み込む事をよくやりますよね?

これめっっっっっっちゃ処理速度が遅いんです

Railsの高速化テクニックの一つに「まずrender partialを減らそう」が入ってくるくらい遅いです(1000回読み込むだけで200msとかかかったりする)

それを高速に表示するように置き換えつつ、ついでにテストしやすくしたり、結合を減らしてカプセル化したり、と色々良い感じにしたものがコイツです

過去の資産とバッティングする事もなく、導入したとしても自分から使わなければ何の影響も与えません

何も考えずにただただ導入して、今後render partialを書きたくなったらググって、ただただこっちを使って書くようにするだけで恩恵がある上に褒められるので全人類いれましょう

turbolinks.js

ページ遷移を良い感じにSPA風味にしてくれる賢いやつです

正直もうこれなしでプレーンで戦うのはもうキツイです

そもそもなんでRailsなどのサーバーサイドレンダリングが遅いと言われるのか?

サイトを見ている時にリンクをクリックしたりして、ページを移動する度にjavascriptファイルやcssファイルのメモリへの読み込みがリセットされて、更にヘッダーやフッターなど全ページで共通なデータなども毎回ページ遷移の度にダウンロードしなおす必要があるためです

ページ遷移の時に一瞬画面が白くなったりするのはそのせいですね

SPAと呼ばれるモノは、一度読み込んだ後はリンクをクリックして遷移している……ように見せかけて実は内部でjsファイルで出力を切り替えているだけなのでブラウザ本来のページ遷移を行っていないんです(zenn.devもそう)

turbolinksはその「ブラウザ本来のページ遷移を奪い取ってSPAと同じように再読込させずに遷移させる」という仕組みなので、この点だけで言えばturbolinksを入れればSPAサイトと全く変わりないヌルヌルなページ遷移を実現することが出来ます

今までのjs資産(特にjquery)との兼ね合いが良くなかったり、挙動がいまいちわからないって理由でoffにしてる人が多いですがこれはもうRailsで書くと決めたならONにしましょう

確かに独特の癖がありますがそれ以上にメリットが大きいです。form remote: trueとの組み合わせなんて感動レベルです

これに関してはRailsにデフォルトで入ってるしONになってるので何も言わずにそのまま使って下さい

stimulus.js

Basecamp(DHHの所属する会社)が作った小さいjsのフレームワークです

今確認したら 42kb / 8.8kb#gzip だったので相当小さいですね

これの特徴というかこれを選んだ理由はたった一つです

他のjsフレームワークが「jsで出力して、jsで操作して、jsで……」とjs主体なのに対して、こいつは

「Railsで出力したhtmlタグをベースに操作」「Railsで表示されるバリデーションに対して操作」「Railsで……」と、あくまでも**「Railsがviewを吐き出すからそれを加工する」**という立場を守ってくれます

当然turbolinksとの相性も良いので特に意識することなく使えます

本当はもっともっとシンプルなものを探したかったのですが、上に書いたように「jsが主役」ではなく「出力されたHTMLに手を加える」という立場のフレームワークでいいものが殆ど無かったのでこれを採用しました

イメージとしては「jqueryではごちゃごちゃになるDOM操作をすっきりキレイに、わかりやすく書けるヤツ」くらいに考えておいてもらえればと思います

続きは飽きたので適当に箇条書きで

  • stimulusはcontrollerを作って紐付けるけどかなりこれは仕組み的にしんどい(読解コストが高い)
  • 従って、view componentをsideなんちゃら形式にして
- app 
  -  components
    - items
      - card
        - component.js
	- component.erb
	- component.rb
	- component.css

こんな感じのディレクトリ構成にする(つまり、全てのコンポーネントファイルの名前が「component」になる。この点は見通し悪いしイマイチだけど仕組み上これがベストなんですよね……

  • そして、このjsは自動でrailsがどうにかしてくれるわけではなく、自分で何かしらの手段で読み込まないといけない

  • 従って、gulpあたりを使って/app/components/*.jsを監視して、変更があったら /app/javascript/controllers/components/ に突っ込むようにする。その際はdirectory構成から勝手に名前をつけてやると良い

  • 例えば上の例なら items-card-component_controller.js

  • そして、/app/components/acpplication_component.rb を作ってそこに

  def stimulus_name
    "components--#{self.class.to_s.downcase.gsub('::', '-')}"
  end

こういうメソッドを作ってやって、後はcomponentの中で

<div data-controller="<%= stimulus_name %>"> ....
  • とやるだけで、自動でリンクしてくれるので解読コストも手間も劇的に下がる

  • これで基本的にはやりたい放題気持ちよく書けるし、困った時はjqueryに逃げられるので大抵のアプリはこれで問題なく書けると思います

  • cssも似たような感じだけど、これに関してはどこにおいてもいいので適当

  • ただ、そもそもcssとhtmlを右目と左目で見比べながら読むのは非常にコストが高いので、できればtailwind.css を入れたほうが良いです

で、この構成はどれくらい良いの?

reactで成功しているcomponent化の概念をrailsで使いやすく更にstimulusと結合した形で持ってきているだけなので、初心者から上級者まで誰でも使いやすいかなりおすすめの構成だと思います

バトル漫画で言えば堅実すぎてつまらないけど大抵の人には勝つメガネ生徒会長キャラみたいな構成です

面白そうだと思ったら試してみて下さい

もっと良い構成を模索中なのでつっこみや改善できそうな場所などあればお待ちしてます