47
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rails7のnewコマンドのオプションが多すぎて分からなくなった時のために(フロントエンド多め)

Last updated at Posted at 2023-03-31

Rails7から色々なオプションが増え、整理ができていなかったので、いろいろ試して整理してみました。
同じような人がいるかと思ったので、参考になると嬉しいです。

rails ver: 7.0.4.2

Rails7ではデフォルトの構成に変化が色々ありました。特にフロントエンドに関する部分が大きく変わったので、そこを重点的に説明していきます。

オプションの確認

rails new -h

(結果は長いので省略します)

1. JavaScript に関するオプション

新たにJavaScriptのビルドのツールを選択できるようになりました。
デフォルトは「importmap」となっています。 (Import mapsについては後で説明します)

rails newのoption
-j, [--javascript=JAVASCRIPT]
# Choose JavaScript approach [options: importmap (default), webpack, esbuild, rollup]
# Default: importmap

importmap-rails

importmapを選択すると、rails newで以下のコマンドが実行され、importmap-railsのデフォルト設定が作成されます。

       rails  importmap:install

今まではwebpackerが使われていましたが、importmap-railsがデフォルトとなりました。
importmap-railsを使うことで、Node.jsを使ったJSファイルのビルドが不要になります。

この変更の背景について、DHHの記事で説明されています

  • IE11のEOLにより、JavaScriptをES5に変換する必要がなくなった
  • HTTP2の普及により、多くのファイルを1つにまとめる必要がなくなった
    • バンドルをすると少しの変更でもキャッシュのexpireが必要というデメリットがある
  • Import mapsにより、モジュールの依存関係にファイル名を使わずに済むので、モジュールの内容が変わっても呼び出している側のファイルのキャッシュを使い回せる

というものです。

Import mapsとは、JavaScriptモジュールをimportする際に、モジュール解決の方法を制御できるJSONオブジェクトです。モジュールと、その名前のマッピングを用意しておくことで、import文を使ったときに対応するモジュールを解決してくれます。1

これにより、import React from 'react'のように書かれたJavaScriptが、そのままブラウザ上で動かせるようになります。

importmap-railsではconfig/importmap.rbでその対応表を作ります。

config/importmap.rb
# Pin npm packages by running ./bin/importmap

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"

このように書くことで、モジュール解決ができ、JavaScriptをビルドしなくてもブラウザ上で動作させることができるようになります。

ちなみに、Import mapsがまだ対応していないブラウザでも、es-module-shims がインストールされるので動作するようです。

その他のオプションを選択したい (bun, webpack, esbuild, rollup)

2023/9/29追記 Rails v7.1.0.beta1でBunが追加されたので別記事にまとめています


importmap以外にもbun, webpack, esbuild, rollupを選択することができます。
importmapだとTypeScriptを使ったり、JSXを使ったりができないので、これらを使いたいときには他のツールが候補になります。

これらを選択した場合、rails newで以下のようなコマンドが実行されます。

       rails  javascript:install:esbuild

このとき、./package.jsonが生成され、esbuildがインストールされます。

そして、Railsとこのビルドツールの間をうまくつなぐ役割として jsbundling-rails があります。
assets:precompileを実行すると、yarn buildの結果がapp/assets/buildsに出力され、Asset pipilineと組み合わせることができます。

2. CSS に関するオプション

rails newのoption
-c, [--css=CSS]
# Choose CSS processor [options: tailwind, bootstrap, bulma, postcss, sass... check https://github.com/rails/cssbundling-rails]

Tailwind CSS, Bootstrap, Bulma, PostCSS, Dart Sassが選択できます。
JavaScriptのときと同様に、以下のコマンドが実行されます。

       rails  css:install:tailwind

またCSSの場合は cssbundling-rails がRailsとの間をつなぐ役割を担ってくれます。

CSSのオプションの中でtailwind以外は、一緒にesbuildがインストールされます。tailwindだけはデフォルトでimportmap-railsと tailwindcss-rails がインストールされます。

3. Asset pipeline に関するオプション

これも新しく追加されたオプションです。

rails newのoption
-a, [--asset-pipeline=ASSET_PIPELINE]
# Choose your asset pipeline [options: sprockets (default), propshaft]
# Default: sprockets

Asset pipelineについては、Sprocketsの他に新たにPropshaftが選択できるようになりました。

Asset pipelineに関するオプションを何も指定しない場合、デフォルトでSprocketsがインストールされます。不要な場合は、明示的に--skip-asset-pipelineオプションを指定する必要があります。

Sprockets

元々Asset pipelineは、JavaScriptやCSSなどのアセットをバンドル、minify、圧縮、トランスパイルなどをかんたんに行うために使われていました。また、必要なプロセッサをgemを用いて組み合わせることで、柔軟に処理できました。しかし、importmap-railsがデフォルトになったことで、一部の使い方が今までと変わりました。

例えば、Sprocketsとimportmap-railsを一緒に選択した場合、トランスパイルは行われません。TypeScriptを使用するといったようにトランスパイルが必要な場合は、importmap-railsではなく、esbuildなどの別のツールを使う必要があります。

読み込むファイルはapp/assets/config/manifest.jsに設定します。
そしてbin/rails assets:precompileコマンドを実行してプリコンパイルすると、public/assetsディレクトリに配置され、配信できるようになります。
JavaScriptのファイルはapp/assets/javascriptsではなく、app/javascriptディレクトリにありました。

Propshaft

Propshaftは、Sprocketsに代わる新しいAsset pipeline用のライブラリです。

importmap-railsと組み合わせることで、Asset pipelineにおいてバンドルやminify、コンパイルが不要になるケースが出てきました。そこでSprocketsよりもシンプルで高速なプリコンパイルを実現する目的で開発されました。

ただし、Sprocketsを使用しているアプリケーションをPropshaftに移行する場合、多くの変更が必要になる可能性があります。例えば、Sprocketsでトランスパイルなどを行っている場合、それらの処理を別のツールに置き換える必要があります。そのため、すぐにSprocketsを代替するものにはならないようです。

しかし、新規で rails newをする場合、SprocketsよりもシンプルなAsset pipelineを実現できるので、候補にはなりうると思われます。

importmap-rails や jsbundling-rails/cssbundling-rails と併用する

先程も出てきましたが、デフォルトではSprocketsと一緒にimportmap-railsもインストールされます。Asset pipelineを無効化しないかぎり、これらの組み合わせてでどれにするかを選択します。

4. Hotwire に関するオプション

こちらも新たに追加されたHotwireに関するオプションです。

HotwireはJavaScriptをあまり書かなくても、既存のHTMLとの組み合わせることでSPAのようなページを作ることができるツールです。

rails newのoption
[--skip-hotwire], [--no-skip-hotwire]

明示的に--skip-hotwireを指定しない場合、turbo, stimulusがインストールされます。

       rails  turbo:install stimulus:install

gemはturbo-rails, stimulus-rails、npmパッケージは@hotwired/turbo-rails, @hotwired/stimulusです。
(importmapを使うときは@hotwired/stimulus-loadingもインストールされました)

Hotwire以前

Railsには、 rails-ujs (Rails UJS)Turbolinks がありました。

Rails UJSによって、JavaScriptをほぼ書かなくてもAjaxを使ったformの挙動を実現できていました。また、Turbolinksによって、静的なHTMLであってもページ遷移をSPAっぽくすることができていました。

Rails7でHotwireが導入されるにあたり、TurbolinksはTurboの機能の1つのTurbo Driveとなっています。

また、Rails UJSはdeprecatedになりました。

Turbo + Stimulus

HotwireはTurbo、Stimulus (とStrada)で構成されています。

Turbo

TurboはJavaScriptを書かなくてもSPAのようなページ遷移を実現できるツールです。
Turbolinksが持っていた機能(Turbo Drive)の他にもいくつか機能が追加されています。

JavaScriptを一切書かなくても、Turbo Frameのdata-turbo-frameを使って、HTMLの一部だけを差分更新したりすることができるようになります。

Stimulus

StimulusはJavaScriptのフレームワークです。ただ、Reactなどのように、JavaScriptがHTMLを生成するのではなく、生成されたHTMLにJavaScriptで機能を追加します。

jQuery等では、HTMLを動的に変更するには、セレクタを使って要素を選択し、イベントリスナーの設定をしますが、Stimulusではそれは行いません。HTMLにdata-controllerdata-actionといった属性の設定をすることによって、HTMLとJavaScriptを紐付けます。

<div data-controller="hello">
  <input data-hello-target="name" type="text">

  <button data-action="click->hello#greet">
    Greet
  </button>

  <span data-hello-target="output"></span>
</div>
import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "name", "output" ]

  greet() {
    this.outputTarget.textContent =
      `Hello, ${this.nameTarget.value}!`
  }
}

TurboもStimulusもRailsと切り離されたライブラリなので、素のHTMLの上でも動作させることができますし、他のフレームワークと組み合わせて使うことも可能です。

このあたりについては、他の方が色々と分かりやすい記事を書いているので、そちらを参考にしてみてください。

5. APIモード に関するオプション

APIモードは元々ありましたが、試してみました。

rails newのoption
[--api], [--no-api] # Preconfigure smaller stack for API only apps

APIモードにすると、config/application.rbでconfig.api_only = trueが設定されますが、それ以外にも不要なファイルや設定が読み込まれなくなります。

ファイルやディレクトリを削除しているログ
      remove  app/assets
      remove  lib/assets
      remove  tmp/cache/assets
      remove  app/helpers
      remove  test/helpers
      remove  app/views/layouts/application.html.erb
      remove  public/404.html
      remove  public/422.html
      remove  public/500.html
      remove  public/apple-touch-icon-precomposed.png
      remove  public/apple-touch-icon.png
      remove  public/favicon.ico
      remove  config/initializers/assets.rb
      remove  app/assets/config/manifest.js
      remove  app/assets/config
      remove  app/assets/stylesheets/application.css
      remove  config/initializers/content_security_policy.rb
      remove  config/initializers/permissions_policy.rb
      remove  config/initializers/new_framework_defaults_7_0.rb

ソース: railties/lib/rails/generators/rails/app/app_generator.rb

またimply_options2として、 --skip-asset-pipeline, --skip-javascript, --skip-hotwireも設定されます。

6. minimal (最小限のRailsアプリケーション)

minimalも元々ありましたが、使ったことがなかったので試してみました。

rails newのoption
[--minimal], [--no-minimal] # Preconfigure a minimal rails app

minimalはメタオプションです。メタオプションとは、その他の複数のオプションをまとめて指定するためのオプションです。

ちなみに、apiはオプションをまとめる以外の機能もあるので、メタオプションではありません。

minimalをつけると、以下のオプションをまとめて指定することになります。

  • skip_action_cable
  • skip_action_mailbox
  • skip_action_mailer
  • skip_action_text
  • skip_active_job
  • skip_active_storage
  • skip_bootsnap
  • skip_dev_gems
  • skip_hotwire
  • skip_javascript
  • skip_jbuilder
  • skip_system_test

そのため、最小構成のRailsアプリケーションを作りたいときにrails new hoge --skip-action-mailer --skip-action-mailbox --skip-action-cable ...のようにたくさんオプションをつけなくてもよくなるので便利です。

minimailを設定してもtest_unitはインストールされてしまうので、RSpecを使いたいときは-Tをつけると良いです。

その他のimply options

api, minimal以外にも、これを指定すると、他のオプションも指定されるというものがあります。

  • skip_active_job: skip_action_mailer, skip_active_storage
  • skip_active_record: skip_active_storage
  • skip_active_storage: skip_action_mailbox, skip_action_text
  • skip_javascript: skip_hotwire

詳しくはソースコードを読んでみてください。

感想

最近は、Asset pipelineを使っていないということもあり、Import mapsとかAsset pipeline周りとか、Hotwireとか知っても使わないしなーと思っていたのですが、調べてみるとどうしてこの変更をしたのか等が知れて、とてもおもしろかったです。

正直、bundleやminifyが必要ない!というのは早い気がしますが、今のフロントエンドのトレンドに対して、違った観点からの考え方が知れて新鮮でした。

参考

  1. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap

  2. https://github.com/rails/rails/blob/4716bed6faba761ee945ea35a9a8e34e9035b671/railties/lib/rails/generators/app_base.rb#L185-L209

47
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?