Railsフロントエンドまとめ

概要

Ruby on Railsのフロントエンドで出てくるエコシステムを整理してみました。

Railsのフロントエンド周りは本当にカオスです。

単語の説明

  • webpacker … webpackをRails用に使いやすくwrapしたGem。
  • webpack … javascriptをいい感じに静的アセットとして処理して配信してくれるNode.jsのパッケージであり、モジュールハンドラー。(実はcssやimageもいける)
  • Sprockets … (主に)css, imageを静的アセットとして処理して配信してくれるRailsのGem。
  • Babel … jsのトランスパイラー。

webpackerからwebpackへ。

Railsのフロントエンドエコシステムで大きな変化として、標準だったwebpackerの開発・サポートが終了したことでしょう。
それにより、webpackerの引き剥がし作業が発生し、この記事はその過程で自分の中での整理も込めて書いています。

はい、webpackerはもうretireなようですね。

ということで、文章の中に the switching guide というリンクがあり、その先には jsbundling-rails というgemを使ってwebpackerをwebpackに変換して使い続けるための手順書があります。
実際に、上記の手順書に従って作業をした結果、なんとかwebpackerのgemを削除してアプリを正常に動作させることに成功しました。

webpackerはwebpackをRails用にカスタムしたものだったようですが、多くの処理を隠蔽しすぎていたようですね。。

詰まったところ

01. そもそもwebpackとかwebpackerとかsprocketsとか謎単語が多すぎる。

Short Answet

フロントの技術は変遷が激しいけど、webpack, webpacker, Sprocketsが理解できればなんとか業務を進められる。
特に、それぞれのツールの設定ファイルと実行方法を調べておくと実務で使える。

Long Answer

フロントエンドにあまり明るくなく手探りだったが、バックエンドに比べて考慮事項が少なかったので、数日でキャッチアップできた。
特に、バックエンドでは通信・DB・ミドルウェアなんかの概念が大変だけど、今回のフロントの調査では、ビルド方法がメインだった。
どうやら、フロントのビルドにはいくつも課題があるみたいで。。。

技術検証用のGitリポジトリ

https://gitlab.com/test4844026/rails-frontend-webpacker-sprockets

rails 6.1.4, wepbacker, sprockets-railsの環境作りで分かったこと

  1. まず、やっぱり環境構築は使い捨てのDockerfileに限るね!
  2. Webpackerはyarn(ヤーン)を使うけど、デフォルトではエラーになる。
  3. rails v 6.0.6はdatabaase関連でphcicsとかいうのでエラーが出るので6.1.4に変えたら解消した。
  4. Webpackerに対応したRubyアプリケーションを作成するには「rails new」コマンドで「–webpack」オプションを追加すればいけたらしいから最新のv7にすればよかった!後の祭り。

02. なぜwebpackとsprocketsという似たようなツールが共存しているのか。

Short Answet

Railsの開発者がSprockets推しみたく、webpackはjs担当として頑張ってくれとのこと。

Long Answer

本来、RailsにはSprocketsとWebpckerが付いていて、css,imageはSProckets。
javaascriptはWebpackerという役割分担だったみたい。
1つに統一しなかった理由は、webpackがjavascriptコード内でcssをjsのオブジェクトのように扱っていたから見たい。
phpのコードの中でjsの変数を展開するのが気持ち悪いように、jsとcssは分けて管理して、ごちゃごちゃにしたくないっていう感じなのでしょうか。
すごい理解できます。
でも、Railsを使っている僕たちからしたら、1つにしてくれた方が嬉しいかも!!
とはいえ、Sprocketsでもjsは管理できるし、webpackでもcss, imageは管理できる。
公式的には2つのツールは共存してるけど、使い方によっては統一できます。
とはいえ、Rails Wayをいくのであれば公式に従って二刀流で行く方が手戻り少なそうですね。
二刀流といえば、野球の彼が結婚したみたいで…はい、関係ない。

03. webpackではなくsprocketsだけではダメなのか?

Short Answet

これは今調査中ですが、上記の理由で、一旦はなしですかね。

Long Answer

一旦、sproketsだけ!webpackだけ!でRailsアプリを作ってみて考えようと思います。
RailsやらLaravelやらWordpressやらをやるときに思うんですけど、Dockerを使えばサクッと環境を作れるので検証用にはぜひ、Dockerをお使いください。
間違ってもパソコンの中に直接npm installなんかするような環境構築の仕方だと、間違いなく土日が環境だけで潰れます。
Dockerならdocker compose up -d この1行だけで環境が作れちゃうからね!

検証してみた

webpacker

  • 検証用GItリポジトリ
  • 感想 … app/javascript/packsを起点にアセットを配置するだけでオートコンパイルしてくれるので、ブラウザを更新するだけで反映を確認できるので便利。

sprockets

  • ポイント
    • デフォルトで存在しなかったjavascriptに関して、app/assets/config/manifest.jsに定義する必要があった。
    • javascript_include_tag, stylesheet_link_tagでwebpackerとの切り替えをする必要があった。
    • webpackerと違って、画像をpublic以下にビルドし直すようなことはせず、assetsから直接配信されているみたい。

その他瑣末な疑問

webpackerの設定ファイルはどこ?

Webpacker用の設定ファイルはconfig/webpaker.ymlとconfig/webpack/environment.jsがある。
後者はRailsがよしなに設定したwebpack.config.jsに手を加えるためのファイル。

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  webpack_compile_output: true
# 上からわかるようにapp/javascript/packs以下が参照ディレクトリで、プリコンパイルしたものはpublic/packs配下に出力されるようにデフォルトで設定されている。

https://qiita.com/NoSuke23/items/aa3bea824367ccf163eb

webpackerのプリコンパイル
$ bin/webpack

また以下のコマンドを実行してサーバーを立てれば、JSに変更があるたびにコンパイルされる(WSLだと重くなるので使ってない)。

$ bin/webpack-dev-server
webpackerではプリコンパイルコマンドを打たなくてもアセットを使えるのはなぜ?

$ rails assets:precompileこれ。

アプリ内のSprocketsはcss,image,jsどれをサポートしてるのかどこでわかる?

よくファイル名に出てくる@って何?

npmパッケージで名前空間を分けるための、ユーザー名。
npmには無数のパッケージがあり、(偶然にも・最悪なことに)他とかぶってしまう可能性があります。
そこで、パッケージ名の前に「@ユーザー名」をつけることで名前空間を分けて被りを予防しているっていうわけですね!
実際、Railsアプリでnode_modulesの中を見てみると、@から始まるディレクトリがありますね。

Sprocketsが参照するディレクトリは?

app/assets … アプリ固有
lib/assets … ???
vender/assets … 外部リソース(gemで入れたbootstrapとか)

Sprocketsのマニフェストは2つある?

app/assets/config/manifest.js
Rails.application.config.assets.precompile

なぜapplications.scssで同じディレクトリにないはずのファイルを@importできるの?

それはきっとsprocketsのデフォルト3箇所、もしくは別途定義した場所を自動で読みにいってくれるから。(gemでinstallしたvendor内のbooytstrapのscssを@importで読めるのはそういうこと)
ちなみに、読んでくるファイルのパスは、以下のコマンドをrails cで打ち込むと確認できる。

$ Rails.application.config.assets.paths
sprocketsもwebpackerみたいにプリコンパイルできるの?

これでできるよ

$ rails assets:precompile
両方のタグを書いてみるとどうなる?

shortAnswer: 両方適応されるけど、cssはwebpackの方が後に読まれるので、結果優先されている。javascriptは書いた順に実行されるので制御できる。

Webpackerで追加されたファイル

ファイル説明
bin/webpackwebpackでコンパイルを実行
bin/webpack-dev-serverwebpack-dev-serverを実行
config/webpacker.ymlエントリーポイントやdevelopやproduction固有の設定を定義する。
webpackのwebpack.config.jsに相当。
node_modules/node.jsのモジュール群の保管場所
package.jsonnode.jsの依存関係を解決
config/webpack/environment.jsローダーやプラグインの設定
app/javascript/webpack用のソースディレクトリのルート。
webpacker.ymlで変更可能
app/javascript/packs/application.jsデフォルトのエントリーポイント。
開発規模に応じて、複数のエントリーポイントを定義できる

参考資料