🎐

Rails6にTailwindCSSを導入し、tailwind.config.jsでカスタマイズもできるようにする

2021/11/21に公開

きっかけ

TailwindCSSを使ってみようと思って、Tailwind Playで練習を積み、「よしRailsでやるか!」と意気込んでいたのですが、環境構築でボロボロに...。

出回っている導入方法は、以下2つがあったのですが、

  1. yarnでTailwindCSSをインストールする
  2. rails/tailwindcss-railsを使って、gemで導入する

1はTailwindとPostCSSとWebpackの依存性がややこしくて、最後まで辿り着かず、2の方はお手軽ながらもtailwind.config.jsの内容がなぜか反映できず、
カスタマイズができなくて辛い...ということで、新たに導入記事を書くことにしました。

環境

  • Rails: 6.1.4.1
  • TailwindCSS: 2

リポジトリ

今回の記事で扱った内容は、以下のリポジトリで確認できます。

https://github.com/IkumaTadokoro/rails6-and-tailswind-sample

アプリケーション作成

まずはサンプルアプリケーションを作成します。

$ mkdir rails6-and-tailwind-sample
$ cd rails6-and-tailwind-sample
$ rails new .
$ rails db:create #sqlite3で試す場合は不要
$ bin/rails s

必要なパッケージのインストール

TailwindCSSの2系は、PostCSSの8系に依存しています。そのため、必要なパッケージをバージョン指定で一括で追加します。

$ yarn add tailwindcss@2 postcss@8 @fullhuman/postcss-purgecss@4 postcss-loader@4 autoprefixer@10
パッケージ 概要 参考
tailwindcss 言わずもがな、今回の主眼。2系です。 Tailwind CSS - Rapidly build modern websites without ever leaving your HTML.
postcss CSSをJavascriptでごにょごにょしてくれるやつです PostCSS まとめ - Qiita
postcss-purgecss フレームワークを利用することで肥大化するCSSのうち、実際に使うCSSのみを抽出することで動作を軽くしてくれるプラグインです PurgeCSS - Remove unused CSS
postcss-loader CSSをJavaScriptのコードとして扱わせるCSS loaderのPostCSS版 webpack-contrib/postcss-loader: PostCSS loader for webpack
autoprefixer ベンダープリフィクスなど、ブラウザに合わせた設定が追加されたCSSを生成してくれます PostCSS まとめ - Qiita

TailwindCSSの読み込み

TailwindCSSを読み込むために、CSSファイルを作成します。

$ mkdir app/javascript/stylesheets
$ touch app/javascript/stylesheets/application.css
application.css
@tailwind base;
@tailwind components;
@tailwind utilities;

作成したCSSを読み込ませるために、application.jsimportを追加します。

application.js
# 略
import "channels"
import "stylesheets/application.css" # ADD

Rails.start()
# 略

PostCSSにTailWindCSSを読み込ませるためにrequireを追加します。

postcss.config.js
module.exports = {
  plugins: [
    require('tailwindcss'),
    require('postcss-import'),
    # 略

最後にstylesheet_pack_tagapplication.html.erbに追加します。

application.html.erb
<!DOCTYPE html>
<html>
  <head>
    # 略

    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> # 追加
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

TailwindCSSのconfigを追加

以下のコマンドでディレクトリ直下にtailwind.config.jsが作成されます。

$ npx tailwindcss init
tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

JITモードとpurgeオプションを追加します。

tailwind.config.js
module.exports = {
  mode: 'jit',
  purge: [
    './app/views/**/*.html.erb',
    './app/helpers/**/*.rb',
    './app/javascript/**/*.js',
  ],
  # 略

purgeは先の通り、必要なCSSだけを読みにいき、ビルドサイズを削減するオプションです。
JITはTailwindCSSのJustInTimeモードを有効にするオプションで、ざっくりいうと「早い」モードです。
TailwindCSSの公式プレイグラウンドであるTailwind Playでも有効になっているので、ONにしておけば良いと思います(あんまりよくわかってない)。

動作確認

何だかいけそうな感じなので、ここらで動作確認をしてみたいと思います。

$ rails g controller home index
index.html.erb
<h1 class="text-red-500 text-9xl">Home#index</h1> # TailwindCSSのクラスを適用する(でかくて赤い文字)
<p>Find me in app/views/home/index.html.erb</p>
$ bin/webpack-dev-server
ERROR in ./app/javascript/stylesheets/application.css (./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/dist/cjs.js??ref--5-2!./app/javascript/stylesheets/application.css)
Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
ValidationError: Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
 - options has an unknown property 'config'. These properties are valid:
   object { postcssOptions?, execute?, sourceMap?, implementation? }
    at validate (/Users/tadokoroikuma/RubymineProjects/sandbox/rails6-and-tailwind-sample/node_modules/postcss-loader/node_modules/schema-utils/dist/validate.js:105:11)
    at Object.loader (/Users/tadokoroikuma/RubymineProjects/sandbox/rails6-and-tailwind-sample/node_modules/postcss-loader/dist/index.js:43:29)
ℹ 「wdm」: Failed to compile.

あれ、エラーになってしまいました。

postcss-loaderのエラーを解消

このエラーはどうもpostcss-loaderのoptionの形式が変わったことが原因であるようです。
同じ内容のissueがrails/web-packerのリポジトリに上がっていました。

https://github.com/rails/webpacker/issues/2784

Conversationsを追っていくと、どうもwebpackerのenvironment.jsにスクリプト的なものを書くことで回避できるようです。
というわけで、下記をconfig/webpack/environment.jsに追記します。

environment.js
function hotfixPostcssLoaderConfig (subloader) {
  const subloaderName = subloader.loader
  if (subloaderName === 'postcss-loader') {
    if (subloader.options.postcssOptions) {
      console.log(
        '\x1b[31m%s\x1b[0m',
        'Remove postcssOptions workaround in config/webpack/environment.js'
      )
    } else {
      subloader.options.postcssOptions = subloader.options.config;
      delete subloader.options.config;
    }
  }
}

environment.loaders.keys().forEach(loaderName => {
  const loader = environment.loaders.get(loaderName);
  loader.use.forEach(hotfixPostcssLoaderConfig);
});

動作確認2

$ bin/webpack-dev-server
$ bin/rails s

http://localhost:3000/home/index にアクセスすると...

期待通り、TailwindCSSが適用された状態でVIEWが表示されました!!

tailwind.config.jsでカスタマイズしてみる

デフォルトのTailwindCSSが適用されることを確認できたので、次はtailwind.config.jsを修正して、スタイルをカスタマイズできるか試します。
今回は試しにカスタムの色を作成して、それが適用できるかをチェックします。

まずはVIEWファイルにtext-accentという今回追加する色のクラスを追加します。

index.html.erb
<h1 class="text-accent text-9xl">Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

この状態で確認すると、まだカスタマイズ設定が適用されていないので、スタイルが適用されていない状態になります。

それでは、tailwind.config.jsを開き、カスタマイズを追記しましょう。

tailwind.config.js
# 略
  theme: {
    extend: {
      // 色の設定を拡張
      colors: {
        accent: '#FFB600',
      }
    },
  },
# 略

カスタマイズ内容が適用されたVIEWが表示されました🎉

終わりに

調べている途中で、Rails 7でのフロントエンド周りについて、DHHが解説している動画に出会いました。

https://www.youtube.com/watch?v=JsNtLiph87Y

Rails7からはrails newする際に、--css tailwindとするだけでTailwindCSSが導入できるそうです。これは便利ですね!

というわけで、Rails6系は7系に置き換わり、需要は少なくなると思いますが、この記事がどなたかの役に立てば幸いです😄

GitHubで編集を提案

Discussion