DIGGLE開発者ブログ

予実管理クラウドDIGGLEのプロダクトチームが、技術や製品開発について発信します

Rails7環境での最適なJavaScriptビルドツールの選択ガイド

この記事は Ruby on Rails Advent Calendar 2023 の20日目の記事です。

はじめに

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

バグっぽいのでプルリク出ていないかなと覗いてみたら、丁度出されたみたいでした。 なので今後は大丈夫そうです。 github.com

SprocketsとPropshaft

Sprocketsの後継としてPropshaftが出ています。PropshaftはSprocketsにあったトランスパイルなどの機能はjsbundling-railsなどの他のgemに任せ、配信に必要な最小限の機能だけ提供することで、シンプルに保とうというコンセプトのライブラリのようです。

まとめ

今回、弊社はRails7 + Reactで、jsbundling-rails + esbuildを採用しました。 ただし、プロジェクトの要件によって最適なツールは変わります。 また、この辺りのビルドツールは、実際に利用してみてはじめて分かるようなハマりポイントもあったりします。

この記事が、プロジェクトに適したツールを選択する際の一助となれば幸いです。

DIGGLEのエンジニアのchikugoがお送りしました。

We're hiring!

DIGGLE では共にプロダクトを開発してくれるエンジニアを大募集中です。

少しでも興味があれば、ぜひ下記採用サイトからエントリーください。
カジュアル面談も実施しているので、気軽なお気持ちでご応募いただければと思います!

herp.careers

*1:Hot Module Replacementの略。ウェブアプリケーションの開発中にページの全体リロードをせずに、特定のモジュール(例えばCSS、JavaScriptのコード)をリアルタイムで自動更新する仕組み。