🌬️

Recurrent Rails #2 How Tailwind CSS works

に公開

はじめに

Recurrent Rails シリーズです。今回は Tailwind CSS についてキャッチアップします。

今日はここまでできたら OK 👍

  • Tailwind CSS と Rails アプリケーションの連携がわかる
  • 本番のデプロイで注意することがわかる

知ってました?

rails g scaffold で作った画面でここまでマークアップしてくれています。

いつもは GraphQL や JSON サーバーを使って React や Vue と連携することが多いので、ここまで Rails だけで出来るのはかなり嬉しいですね。

📝 rails new は Recurrent Rails #1 How to start Rails app を参照してください。

連携どうしてるの?

bin/dev または bin/setup で Rails アプリケーションを起動しています。ログを見てみましょう。プロセスが web と css ふたつありますね。ひとつのコマンドで複数のプロセスを起動するには Foreman を使います。

❯ bin/dev
WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
      stringio (>= 0)
      Available/installed versions of this gem:
      - 3.1.6
      - 3.0.4
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
21:58:34 web.1  | started with pid 42733
21:58:34 css.1  | started with pid 42734
21:58:34 web.1  | => Booting Puma
21:58:34 web.1  | => Rails 8.0.2 application starting in development 
21:58:34 web.1  | => Run `bin/rails server --help` for more startup options
21:58:34 web.1  | Puma starting in single mode...
21:58:34 web.1  | * Puma version: 6.6.0 ("Return to Forever")
21:58:34 web.1  | * Ruby version: ruby 3.2.5 (2024-07-26 revision 31d0f1a2e7) [arm64-darwin23]
21:58:34 web.1  | *  Min threads: 3
21:58:34 web.1  | *  Max threads: 3
21:58:34 web.1  | *  Environment: development
21:58:34 web.1  | *          PID: 42733
21:58:34 web.1  | * Listening on http://127.0.0.1:3000
21:58:34 web.1  | * Listening on http://[::1]:3000
21:58:34 web.1  | Use Ctrl-C to stop
21:58:35 css.1  | ≈ tailwindcss v4.1.3
21:58:35 css.1  | 
21:58:35 css.1  | Done in 53ms

Foreman is 誰

Foreman は Procfile.dev にある内容でプロセスを起動してくれます。

web: bin/rails server
css: bin/rails tailwindcss:watch

bin/rails tailwindcss:watch が何をしてくれるか見てみましょう。

tailwindcss:watch を調査

まず rails new で --css=tailwind オプションを使うと rails/tailwindcss-rails をインストールします。

タスク定義

rails/tailwindcss-rails でタスクを追加しています。

https://github.com/rails/tailwindcss-rails/blob/f722f192de0f4d66d137196fc34e3052e9a3ed6f/lib/tasks/build.rake#L14-L28

ビルドコマンド

app/assets/tailwind/application.css を入力として、app/assets/builds/tailwind.css を出力してくれるようです。裏を返せば入力が変わらなければ出力も変わらないということですね。

tailwindcss -i /path/to/app/assets/tailwind/application.css \
            -o /path/to/app/assets/builds/tailwind.css \
            --minify \
            -w

Rails はどこをみてるのか

出力はわかりましたが、結局このファイルをどこで Rails が発見しているか気になりますよね。HTML から辿ってみましょう。

<link rel="stylesheet" href="/assets/tailwind-a7243bd6.css" data-turbo-track="reload">

Propshaft が探索するアセットパスを調べてみます。app/assets/builds がありますね。Propshaft はアセットパスにあるファイルを public/assets にコピーしてくれるので Rails が発見してくれます。

app(dev)> Rails.application.config.assets.paths
=> 
["/path/to/app/assets/builds",
 "/path/to/app/assets/images",
 "/path/to/app/assets/stylesheets",
 "/path/to/vendor/bundle/ruby/3.2.0/gems/stimulus-rails-1.3.4/app/assets/javascripts",
 "/path/to/vendor/bundle/ruby/3.2.0/gems/turbo-rails-2.0.13/app/assets/javascripts",
 "/path/to/vendor/bundle/ruby/3.2.0/gems/actioncable-8.0.2/app/assets/javascripts",
 "/path/to/vendor/bundle/ruby/3.2.0/gems/activestorage-8.0.2/app/assets/javascripts",
 "/path/to/vendor/bundle/ruby/3.2.0/gems/actionview-8.0.2/app/assets/javascripts",
 #<Pathname:/path/to/app/javascript>,
 #<Pathname:/path/to/vendor/javascript>]

本番のデプロイで注意すること

調べる限り注意すべき内容はなさそうです。tailwindcss-rails のドキュメントを見るに assets:precompile をすればよいです。

https://github.com/rails/tailwindcss-rails?tab=readme-ov-file#building-for-production

Discussion