この記事は Ruby on Rails Advent Calendar 2023 の20日目の記事です。
- はじめに
- Rails7のJavaScriptビルドツールの比較
- jsbundling-rails vs Shakapacker
- jsbundling-railsのバンドルの選択肢
- SprocketsとPropshaft
- まとめ
- We're hiring!
はじめに
Rails7は、JavaScriptのデフォルトツールとしてimport-mapsを採用しました。これにより、ブラウザから直接JavaScriptモジュールをインポートすることが可能になりました。また、Node.jsやWebpack、npm、Yarnの必要性がなくなりました。ただし、選択肢はこれだけではありません。例えばjsbundling-railsではトランスパイルやバンドルがサポートされています。
この記事では、Rails7環境下でのJavaScriptビルドツールについて、選択肢を明確にし、それぞれの特徴を解説します。
Rails7のJavaScriptビルドツールの比較
Rails7には、JavaScriptのビルドに使用できる複数のツールが用意されています。(参考) これらのツールはそれぞれ異なる特徴と利点を持っており、プロジェクトの要件に応じて選択することになります。
種類 | 特徴 | 使用シナリオ |
---|---|---|
import-maps | Node.js不要で、JavaScriptモジュールをブラウザから直接インポート可能。 | トランスパイルが不要なシンプルなプロジェクト向け。 |
jsbundling-rails | Node.js要。esbuild、Bun(Node.js不要)、Webpack等を選択可。HMR*1は標準機能ではない。 | Reactを含む複雑なフロントエンドのビルドが必要な場合、またはHMRを利用するプラグインを追加可能。 |
Shakapacker | Webpackerの後継でHMRサポート。 | 高度なビルドプロセスとHMRを要するReactプロジェクト向け。 |
Sprockets | CoffeeScriptやSCSS/Sassのトランスパイル。JSXやTypeScriptにはWebpackやBabelが必要。最小化・難読化も可能。 | 複数のツールと併用して、アセット管理を行う場合に適している。 |
選択のポイント:
- Reactを利用する場合、import-mapsは適切ではありません。代わりにjsbundling-railsやShakapackerを検討してください。
- Reactを使用せず、トランスパイルやバンドルが必要ないシンプルなプロジェクトの場合、import-mapsが適しています。
- Sprocketsは、他のツールと併用してアセットの管理を行う場合に有効です。
ちなみに弊社ではRails7でReactを利用するので、その前提で選定を進めます。
jsbundling-rails vs Shakapacker
Rails7でReactを使用する際の主要な選択肢として、jsbundling-railsとShakapackerがあります。これらのツールは異なるアプローチを提供し、それぞれ独自の長所と短所があります。
Rails: Webpacker(Shakapacker)とjsbundling-railsの比較(翻訳)
jsbundling-rails
長所
- シンプルな設定: jsbundling-railsは設定が簡単で、迅速にプロジェクトを立ち上げることができます。
- 柔軟性: esbuild、Bun、Rollup.js、Webpackなど、複数のバンドラーをサポートしており、プロジェクトのニーズに合わせて選択可能です。
短所
- HMRのサポート不足: 標準ではHot Module Replacement(HMR)をサポートしていませんが、プラグインを使用することで対応可能です。
Shakapacker
長所
- HMRサポート: ShakapackerはHMRをネイティブでサポートしており、開発プロセスをより効率的にします。
- Webpackerの後継: Webpackerユーザーにとってなじみ深く、既存のWebpackベースの設定やプラグインを容易に統合できます。
短所
- 設定の複雑さ: Webpackに基づいているため、設定が複雑になる傾向があり、初心者にはやや敷居が高いです。
- ビルド速度: Webpackを使用しているため、esbuildなどの新しいツールに比べてビルド速度が遅い場合があります。
弊社ではビルド速度なども勘案して、jsbundling-railsを選択しました。
jsbundling-railsのバンドルの選択肢
jsbundling-railsにはBun, esbuild, Rollup.js, Webpack の選択肢があります。
以下、Google Trendsでの検索結果になります。
(Bunについては別のものが対象になりそうなので、Google Trendsの対象から除外しました)
esbuildが最近少し検索が増えてきたというのと、Rollup.jsがほとんど検索されてないという傾向にあるようです。
それぞれについて以下になります。
Bun
Bunは、JavaScriptおよびTypeScriptプロジェクトのための高速なオールインワンツールキットです。これには、ランタイム、バンドラー、テストランナー、Node.js互換のパッケージマネージャーが含まれています。また、Node.jsの多くのAPIをネイティブに実装しており、Node.jsの代替として設計されています。
esbuild
esbuildは、JavaScript、TypeScript、CSSファイルなどを高速にバンドルするためのツールです。その主な特徴は、非常に高速なビルドとバンドルの速度で、多くの既存のJavaScriptバンドラーよりも速く動作します。
Rollup.js
Rollup.jsは、JavaScriptのモジュールバンドラーです。ES6モジュール構文を使用してファイル間の依存関係を解析し、それらを一つのバンドルにまとめます。効率的なTree shaking(不要なコードを除去する最適化手法)をサポートしています。これにより、最終的なバンドルのサイズが小さくなり、パフォーマンスが向上します。
Webpack
Webpackは、JavaScriptのモジュールバンドラーです。コードベースのモジュールをマッピングし、一つまたは複数のバンドルにまとめることで、ブラウザで使用できるようにします。
比較
Bun | esbuild | Rollup.js | Webpack | |
---|---|---|---|---|
ビルド速度 | 1倍 | 1.76倍 | 188倍 | 224倍 |
ES6 | ○ | ○ | ○ | △ |
TypeScriptのトランスパイル | ○ | ○ | △ | △ |
JSXのトランスパイル | ○ | ○ | △ | △ |
Tree shaking | ○ | ○ | ○ | × |
△としている所は単体での機能提供はなく、プラグインなどが別途必要になります。 ただ、できることの基本的な機能に差異は余りありません。
違いが出ているのはビルド速度でBun調べのパフォーマンス計測では、Bunを1倍とすると最大200倍以上の差が発生しているようです。ちなみにBunはZigベース。esbuildはgolangベースで書かれているそうです。
Bunがまだjsbundling-railsで採用されたばかりという所から様子見も含めて、今回は jsbundling-rails + esbuildの利用としました。
esbuild利用の補足
jsbundling-rails + esbuild + npmを利用している場合に ./bin/rails assets:precompile
のコンパイル実行はエラーとなります。
理由は、jsbundling-rails内でビルド時にpackage-lock.json
の存在確認をしていないからです。
def build_command return "bun run build" if File.exist?('bun.lockb') || (tool_exists?('bun') && !File.exist?('yarn.lock')) return "yarn build" if File.exist?('yarn.lock') || tool_exists?('yarn') raise "jsbundling-rails: No suitable tool found for building JavaScript" end
バグっぽいのでプルリク出ていないかなと覗いてみたら、丁度出されたみたいでした。 なので今後は大丈夫そうです。 github.com
SprocketsとPropshaft
Sprocketsの後継としてPropshaftが出ています。PropshaftはSprocketsにあったトランスパイルなどの機能はjsbundling-railsなどの他のgemに任せ、配信に必要な最小限の機能だけ提供することで、シンプルに保とうというコンセプトのライブラリのようです。
まとめ
今回、弊社はRails7 + Reactで、jsbundling-rails + esbuildを採用しました。 ただし、プロジェクトの要件によって最適なツールは変わります。 また、この辺りのビルドツールは、実際に利用してみてはじめて分かるようなハマりポイントもあったりします。
この記事が、プロジェクトに適したツールを選択する際の一助となれば幸いです。
DIGGLEのエンジニアのchikugoがお送りしました。
We're hiring!
DIGGLE では共にプロダクトを開発してくれるエンジニアを大募集中です。
少しでも興味があれば、ぜひ下記採用サイトからエントリーください。
カジュアル面談も実施しているので、気軽なお気持ちでご応募いただければと思います!
*1:Hot Module Replacementの略。ウェブアプリケーションの開発中にページの全体リロードをせずに、特定のモジュール(例えばCSS、JavaScriptのコード)をリアルタイムで自動更新する仕組み。