`rails new` のオプションから直近のRailsコンポーネントの変遷をザックリと読み解く

## はじめに

こんにちは、2024年3月から CAMPFIRE でバックエンドエンジニアしている @snaka です。

Advent Calendar としてブログ記事を書くのも、Qiita に記事を書くのも久しぶりになります。

数週間前に [Omotesando.rb でLTする機会をいただいた]()ので、そのときの発表内容について記事の形にまとめておこうと思います。

資料は以下です。

<script defer class="speakerdeck-embed" data-id="3f0bb40e03c9406ca9471a8c1a6c7c84" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

## `rails_new_flags` リポジトリの紹介

リポジトリは以下で公開しています。

https://github.com/snaka/rails_new_flags

このリポジトリでは、Rails の直近のバージョン(6.1.x 〜 8.0.x)について `rails new` のフラグ(オプション)の有無でどのような差分が出てくるかを GitHub 上で Diff 表示できます。

たとえば、Rails 7.0.x 系で追加になった `--javascript=esbuild` を指定すると importmap 関係の設定ファイルが削除されて、 package.json に依存関係および build スクリプトとして esbuild が追加されているのがわかります。

表の基本的な使い方は、差分を確認したいフラグ/バージョンの ↔️ アイコンをクリックして

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8219/8d7f1ce7-4f30-2fe5-0459-a1a552f145bb.png)

差分(フラグなしで実行した場合との差分)を確認する。という使い方になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8219/3f11f5ad-67f3-df34-7427-72ff779e63ac.png)


## この記事の内容

この記事では、前述のリポジトリを参考として、「近年 Rails を構成するコンポーネントにどのような変化があったのか」というのを `rails new` のフラグの増減という側面から眺めて見るというものです。


## Rails 6.1.x ⇒ 7.0.x

Rails 7.0.x で導入されたものを見ていきます。

### asset pipeline で propshaft が選択可能に

flag | 🔎 6.1.7.8 | 🔎 7.0.8.4
-- | -- | --
--asset-pipeline=propshaft | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-asset-pipeline-propshaft)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--asset-pipeline=sprockets | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-asset-pipeline-sprockets)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)

- デフォルトは sproket ですが、 `--asset-pipeline=propshaft` を指定することで propshaft を利用することができるようになっています
- propshaft は sprockets に代わる次世代のアセットパイプラインで、HTTP/2 の普及やインターネットの高速化など現代の状況に合わせて、複雑難解だった sprockets よりシンプルな仕組みになっているようで、 Rails 8 からアセットパイプラインのデフォルトになっているようです

https://github.com/rails/propshaft

### jsbundling-rails / cssbundling-rails gem によって JavaScript バンドラや CSS フレームワーク(?) を選択できるように

flag | 🔎 6.1.7.8 | 🔎 7.0.8.4
-- | -- | --
--css=bootstrap | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-css-bootstrap)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--css=bulma |	- |[↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-css-bootstrap) [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--css=postcss |	- |[↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-css-bulma) [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--css=sass| - |[↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-css-postcss) [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--css=tailwind| - |[↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-css-sass) [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--javascript=esbuild | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-javascript-esbuild)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--javascript=importmap | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-javascript-importmap)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--javascript=rollup | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-javascript-rollup)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--javascript=webpack | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-javascript-webpack)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)


- Rails 7.0.x のデフォルトでは importmap ですが、プロダクトの状況によっては従来どおり Webpack のような JS バンドラや Sass のような CSS プリプロセッサが必要なケースもあり、そのような状況にも対応できるようになっているようです 
- jsbundling-rails 自体は bun, esbuild, rollup.js, webpack などに対応しているようです
- cssbundling-rails は bootstrap, bulma, postcss, sass, tailwind などに対応しているようです

https://github.com/rails/jsbundling-rails

https://github.com/rails/cssbundling-rails


### Turbolinks の後継として Hotwire が導入された

flag | 🔎 6.1.7.8 | 🔎 7.0.8.4
-- | -- | --
--skip-hotwire | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.0.8.4..7.0.8.4-skip-hotwire)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.0.8.4)
--skip-turbolinks | [↔️](https://github.com/snaka/rails_new_flags/compare/6.1.7.8..6.1.7.8-skip-turbolinks)  [🔎](https://github.com/snaka/rails_new_flags/tree/6.1.7.8) | -


- Rails 7.0.x から Hotwire がデフォルトで導入されるようになって、それを除外するための `--skip-hotwire` フラグが追加されています
- Hotwire を構成する gem は turbo-rails と stimlus です
- turbo-rails を構成する要素は Turbo Drive, Turbo Frames, Turbo Streams です
- (Hotwire まだ良くわかっていないので使い所を探っていきたいです)

https://turbo.hotwired.dev/handbook/introduction

https://stimulus.hotwired.dev/

### listen, spring, webpacker などの gem がデフォルトから外れた

flag | 🔎 6.1.7.8 | 🔎 7.0.8.4
-- | -- | --
--skip-listen | [↔️](https://github.com/snaka/rails_new_flags/compare/6.1.7.8..6.1.7.8-skip-listen)  [🔎](https://github.com/snaka/rails_new_flags/tree/6.1.7.8) | -
--skip-spring |  [↔️](https://github.com/snaka/rails_new_flags/compare/6.1.7.8..6.1.7.8-skip-spring)  [🔎](https://github.com/snaka/rails_new_flags/tree/6.1.7.8) | -
--webpacker |  [↔️](https://github.com/snaka/rails_new_flags/compare/6.1.7.8..6.1.7.8-webpacker)  [🔎](https://github.com/snaka/rails_new_flags/tree/6.1.7.8) | -


- webpacker は importmap-rails がデフォルトになったことで外れているようです
- spring を導入するかどうかはオプションになったようです (一応 Gemfile にはコメントとして残されているようです)
- listen が外された経緯としては以下の PR にあるようですが... その主張の背景などは調べきれませんでした

あとで読む:

https://github.com/rails/rails/pull/42985


## Rails 7.0.x ⇒ 7.1.x

### デフォルトで Docker に対応した

flag | 🔎 7.0.8.4 | 🔎 7.1.4
-- | -- | --
--skip-docker | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.1.4..7.1.4-skip-docker)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.1.4)

- `rails new` するとデフォルトで `Dockerfile`, `.dockerignore` などが作られるようになっています

### JS バンドラとして bun が利用可能になった

flag | 🔎 7.0.8.4 | 🔎 7.1.4
-- | -- | --
--javascript=bun | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.1.4..7.1.4-javascript-bun)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.1.4)


- 7.0.x 系でも jsbundling-rails のバージョンが上げれば bun を利用可能だと思います(要検証)が、 `rails new` のオプションとして利用可能になったのは 7.1.x 以降のようです


## Rails 7.1.x ⇒ 7.2.x

### Devcontainer に対応した

flag | 🔎 7.1.4 | 🔎 7.2.1
-- | -- | --
--devcontainer | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.2.1..7.2.1-devcontainer)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.2.1)

- `--devcontainer` で `.devcontainer/` 配下に以下のファイルが作成されるようになっています
    - `Dockerfile`
    - `compose.yaml`
    - `devcontainer.json`
- (個人的には Devcontainer の開発は便利だと思う点もありながら、制限が多くてあまり積極的に活用していないのが実情ですが... )

https://code.visualstudio.com/docs/devcontainers/containers

https://containers.dev/

### Rubocop, Brakeman がデフォルトで入るようになった

flag | 🔎 7.1.4 | 🔎 7.2.1
-- | -- | --
--skip-brakeman | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.2.1..7.2.1-skip-brakeman)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.2.1)
--skip-rubocop | - | [↔️](https://github.com/snaka/rails_new_flags/compare/7.2.1..7.2.1-skip-rubocop)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.2.1)

- デフォルトで rubocop, brakeman が導入されるようになっていて、 `--skip-*` オプションでそれぞれ外せるようになっています
- Rubocop はほぼ必須なのでデフォルトで入るようになったのは個人的には嬉しいポイントです
    - 実際に導入されるのは rubocop-rails-omakase という gem のようです
    - Omakase の設定内容をまだ把握していないので、後でじっくり見ておきたいと考えています

https://github.com/rails/rubocop-rails-omakase

- Brakeman はコードを静的解析してセキュリティな問題を洗い出してくれる gem です
- まだ実践導入したことがないのですが、機会を見つけて手元のプロダクトコードで動かしてみて、良さそうであれば導入していきたいと考えています

https://github.com/presidentbeef/brakeman



### GitHub Action 用の workflow 設定 yaml ファイルが用意されるようになった

flag | 🔎 7.1.4 | 🔎 7.2.1
-- | -- | --
--skip-ci | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/7.2.1..7.2.1-skip-ci)  [🔎](https://github.com/snaka/rails_new_flags/tree/7.2.1)


- GitHub Actions でワークフローを実行するための雛形 ( `.github/workflows/ci.yml`, `.github/dependabot.yml` ) がデフォルトで 作成されるようになっています
- `--skip-ci` でこれらの出力を抑制できます


## Rails 7.2.x ⇒ 8.0.x

Rails 8 についてはあまり知識が無く、コメントが感想ベースになりますが... そのうち触っていきたいとは思ってます... (そのうち)

### デプロイツールの kamal に対応した

flag | 🔎 7.2.1 | 🔎 8.0.0.beta1
-- | -- | --
--skip-kamal | - | [↔️](https://github.com/snaka/rails_new_flags/compare/8.0.0.beta1..8.0.0.beta1-skip-kamal)  [🔎](https://github.com/snaka/rails_new_flags/tree/8.0.0.beta1)


- 名前は「[古代アラブの航海用具](https://exploration.marinersmuseum.org/object/kamal/)」に由来しているようです
    - Kbernetes がギリシャ語の「舵取り」「水先案内人」を指す語句を由来としているのと同様に、Ship(「船」そのもの以外に、商品などを「出荷する」という意味もある) に由来するものなのかな？と思ったりしました

https://kamal-deploy.org/

https://github.com/basecamp/kamal

### solid シリーズ (solid_cache, solid_queue, solid_cable) がデフォルトで導入される

flag | 🔎 7.2.1 | 🔎 8.0.0.beta1
-- | -- | --
--skip-solid | - |  [↔️](https://github.com/snaka/rails_new_flags/compare/8.0.0.beta1..8.0.0.beta1-skip-solid)  [🔎](https://github.com/snaka/rails_new_flags/tree/8.0.0.beta1)

- 従来 Redis をバックエンドとして利用することの多かった Cache, Job Queue, Pub/Sub を RDBMS という触れ込み(?) の Solid シリーズが標準で導入されます
- インフラ構成要素として Redis が不要になることで、管理コストやホスティング先の自由度も上がったりするので良さそう、と思ってたりします

https://github.com/rails/solid_cache

https://github.com/rails/solid_queue

https://github.com/rails/solid_cable

### デフォルトで Thruster に対応している

flag | 🔎 7.2.1 | 🔎 8.0.0.beta1
-- | -- | --
--skip-thruster | - | [↔️](https://github.com/snaka/rails_new_flags/compare/8.0.0.beta1..8.0.0.beta1-skip-thruster)  [🔎](https://github.com/snaka/rails_new_flags/tree/8.0.0.beta1)

- Thruster は、これまでプロダクション環境などで Nginx が担っていた SSL termination や static asset の配信などの Puma の負荷を軽減するものという認識です
- `./bin/thrust ./bin/rails server` のように Rails の起動を `thrust` コマンドを経由することで設定なしでそのまま使えるのが魅力だと思いました
    - Nginx 用の設定ファイルやコンテナイメージのメンテナンスが結構面倒なので、その負担がなくなるのは単純に嬉しい
    - プロダクションにそのまま導入するのは難しいとは思うので、何かの機会に Thruster 試してみたいとは思っています 

## おわりに

ざっと `rails new` のフラグの変遷を追いかけて、そこから Rails を構成するコンポーネントの変化をざっと見ていきました。

後半（直近のバージョン）は実際に触れていないため、コメントが雑な感じになってしまいましたが... 今回確認できなかった部分はそのうち検証してみて、良さそうなものはプロダクション環境に取り入れたいなと、考えています。