はじめに
12月15日に
Rails 7.0
がリリースされました。今回の変更の中でおそらく一番大きな変更になるのは、フロントエンド周りで、
Node.js
が(標準で)使われなくなった点ではないでしょうか。
今回は、そのあたりの経緯と新たに追加されたGemについて紹介します。
脱Node.jsの経緯
“So despite what a leap forward ES6 everywhere, ubiquitous HTTP2, and import maps combine to present, there’s clearly still a class of apps that’ll need Webpack. Not everyone can take these things out yet, but those who can will be mightily pleased.” https://t.co/PUXa1j44wb
— DHH (@dhh) August 12, 2021
DHH氏のブログ「Modern web apps without JavaScript bundling or transpiling」によると、3つの理由が挙げられています。
- 主要ブラウザがES6をサポート
- HTTP/2の普及
- Import Mapsの存在
まず1つ目の理由は、主要なブラウザが軒並み
ES6
をサポートした事により、
ES6
で書かれたコードをトランスパイルすることなく、そのまま動作するようになったことです。
2つ目の理由は、
HTTP/2
が普及したことにより、
Webpack
でファイルを結合するメリットが薄れたことです。
3つ目の理由は、
Import Maps
によりインポートする
ES Modules
をモジュール名だけで記述できるようになったことにより、コード上での管理が容易になったことです。
Rails 7.0でのアセット管理
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)+importmap-rails
- propshaft(もしくはsprockets)+jsbundling-rails(+cssbundling-rails)
- propshaft(もしくはsprockets)+webpacker(従来どおり)
propshaft
前述のとおり、
propshaft
は
sprockets
の替わりになるアセット管理ライブラリです。
propshaft
は、必要な
ES Modules
ファイルをファイル名にダイジェストを付けて出力先にコピーします。その際、トランスパイル、バンドリング、圧縮などは行わないため、
sprockets
と比べて高速に動作します。
assets:precompile
を呼ぶと、
config.assets.paths
に設定されたすべてのパスのアセットが
public/assets
にコピーされます。この際、
sprockets
と同様にソースファイルは探査され、ファイル名にはダイジェストが付与されます。
また、
asset-path("ファイル名")
というCSS関数が用意されており、プリコンパイル時に
url("/assets/image-f2e1ec14d6856e1958083094170ca6119c529a73.svg")
のように変換されます。
importmap-rails
Rails 7.0
よりJavaScriptアセット処理のデフォルトとして採用されているライブラリです。バージョン管理されたファイルやダイジェスト版に対応した論理名で、ブラウザから直接JavaScriptモジュールをインポートすることができます。
import maps
は現在ChromeやEdgeなどの一部のブラウザでのみサポートされています。これら以外のブラウザで使用するには、
shim
が必要です。
<%= javascript_importmap_tags %>
タグを使用することで、
es-module-shim
が読み込まれて使用できるようになります(この他にも、JSON設定のセットアップや
app/javascript/application.js
とのマッピングも行われます)
JavaScript CDN経由でのnpmパッケージの利用
importmap-rails
では、npmパッケージをJavaScript CDNから取得するようになっています。ここではプリコンパイルされた配布用バージョンが利用可能になっており、それらを高速に配信します。
npmパッケージのピン留め・解除・更新は、
./bin/importmap
コマンドで行えます。このコマンドは
JSPM.orgのAPI
でパッケージの依存関係を解決し、
config/importmap.rb
にファイルをピン留めします。コマンドの実行例は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ./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
のエントリポイントから利用できるようになります。
1 2 | import React from "react" import ReactDOM from "react-dom" |
さいごに
Rails 7.0からのフロントエンド開発環境の変更点を紹介しました。この他にも、Hotwireの変更もありRailsだけでもフロントエンド開発がやり易くなっているようです。