12月15日にRails 7.0
がリリースされました。今回の変更の中でおそらく一番大きな変更になるのは、フロントエンド周りで、Node.js
が(標準で)使われなくなった点ではないでしょうか。
今回は、そのあたりの経緯と新たに追加されたGemについて紹介します。
DHH氏のブログ「Modern web apps without JavaScript bundling or transpiling」によると、3つの理由が挙げられています。
まず1つ目の理由は、主要なブラウザが軒並みES6
をサポートした事により、ES6
で書かれたコードをトランスパイルすることなく、そのまま動作するようになったことです。
2つ目の理由は、HTTP/2
が普及したことにより、Webpack
でファイルを結合するメリットが薄れたことです。
3つ目の理由は、Import Maps
によりインポートするES Modules
をモジュール名だけで記述できるようになったことにより、コード上での管理が容易になったことです。
Rails 7.0
では、新たに4つのGemが登場します。これまでとは異なり、開発者はこれらのGemを自分のプロジェクトに合う組み合わせで採用することになります。
新たに追加されるGemは、propshaft、importmap-rails、jsbundling-rails、cssbundling-railsです。これらを簡単に説明すると、propshaft
はsprockets
に替わるアセットパイプラインライブラリ。importmap-rails
はRails 7.0
からのJavaScriptアセット処理のデフォルトとして採用されたライブラリ。jsbundling-rails
とcssbundling-rails
はどちらも、JavaScript(またはCSS)を任意のbundlerで扱うためのライブラリです。
propshaft
とimportmap-rails
については、後ほどもう少し詳しく紹介します。
importmap-rails
、jsbundling-rails
、cssbundling-rails
はpropshaft
(もしくはsprockets
)と併用する必要があります。
一般的には以下のような組み合わせで使われるのではないでしょうか。
前述のとおり、propshaft
はsprockets
の替わりになるアセット管理ライブラリです。
propshaft
は、必要なES Modules
ファイルをファイル名にダイジェストを付けて出力先にコピーします。その際、トランスパイル、バンドリング、圧縮などは行わないため、sprockets
と比べて高速に動作します。
assets:precompile
を呼ぶと、config.assets.paths
に設定されたすべてのパスのアセットがpublic/assets
にコピーされます。この際、sprockets
と同様にソースファイルは探査され、ファイル名にはダイジェストが付与されます。
また、asset-path("ファイル名")
というCSS関数が用意されており、プリコンパイル時にurl("/assets/image-f2e1ec14d6856e1958083094170ca6119c529a73.svg")
のように変換されます。
Rails 7.0
よりJavaScriptアセット処理のデフォルトとして採用されているライブラリです。バージョン管理されたファイルやダイジェスト版に対応した論理名で、ブラウザから直接JavaScriptモジュールをインポートすることができます。
import maps
は現在ChromeやEdgeなどの一部のブラウザでのみサポートされています。これら以外のブラウザで使用するには、shim
が必要です。
<%= javascript_importmap_tags %>
タグを使用することで、es-module-shim
が読み込まれて使用できるようになります(この他にも、JSON設定のセットアップやapp/javascript/application.js
とのマッピングも行われます)
importmap-rails
では、npmパッケージをJavaScript CDNから取得するようになっています。ここではプリコンパイルされた配布用バージョンが利用可能になっており、それらを高速に配信します。
npmパッケージのピン留め・解除・更新は、./bin/importmap
コマンドで行えます。このコマンドはJSPM.orgのAPI
でパッケージの依存関係を解決し、config/importmap.rb
にファイルをピン留めします。コマンドの実行例は以下のようになります。
./bin/importmap pin react react-dom Pinning "react" to https://ga.jspm.io/npm:react@17.0.2/index.js Pinning "react-dom" to https://ga.jspm.io/npm:react-dom@17.0.2/index.js Pinning "object-assign" to https://ga.jspm.io/npm:object-assign@4.1.1/index.js Pinning "scheduler" to https://ga.jspm.io/npm:scheduler@0.20.2/index.js ./bin/importmap json { "imports": { "application": "/assets/application-37f365cbecf1fa2810a8303f4b6571676fa1f9c56c248528bc14ddb857531b95.js", "react": "https://ga.jspm.io/npm:react@17.0.2/index.js", "react-dom": "https://ga.jspm.io/npm:react-dom@17.0.2/index.js", "object-assign": "https://ga.jspm.io/npm:object-assign@4.1.1/index.js", "scheduler": "https://ga.jspm.io/npm:scheduler@0.20.2/index.js" } }
これで、以下のようにapplication.js
のエントリポイントから利用できるようになります。
import React from "react" import ReactDOM from "react-dom"
Rails 7.0からのフロントエンド開発環境の変更点を紹介しました。この他にも、Hotwireの変更もありRailsだけでもフロントエンド開発がやり易くなっているようです。