Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
22
Help us understand the problem. What is going on with this article?
@d0ne1s

Tailwind on Rails

2020/1/15追記

Rails公式から、TailwindをRailsに組み込むためのgemが出たのでこっちの方が良いかもです。
https://github.com/rails/tailwindcss-rails

なぜTailwind on Rails?

  • クラス名を決める必要がなくなる
  • クラス名の衝突がなくなり、BEMやCSS設計から開放される
  • デザインの修正により不要になったCSSが残ってしまうことがなくなる
  • どの要素にどんなスタイルが当たっているかがすぐにわかる
  • カラーコードやフォントサイズ、ブレイクポイント等の統一性を保ちやすい
  • ネット上に転がっているサンプルコードを気軽に取り入れやすい(他の人が書いたコードでもカスタマイズが楽)
  • スタイルの修正のたびにapp/assets/stylesheets/任意のフォルダ/任意のファイルを開く必要がなくなる

環境

Rails 6.0.3

導入

$ yarn add tailwindcss
$ yarn tailwindcss init
$ mkdir app/javascript/css
$ touch app/javascript/css/tailwind.css
app/javascript/css/tailwind.css
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
app/javascript/packs/application.js
import '../css/tailwind.css';
postcss.config.js
module.exports = {
  plugins: [
    //...
    require("tailwindcss"), //追加
    require("autoprefixer"), //追加
    require("postcss-preset-env")({
      autoprefixer: {
        flexbox: "no-2009",
      },
      stage: 3,
    }),
  ],
};
app/views/layouts/application.html.erb
-  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
+  <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 

動作確認

$ rails g controller test index
config/routes.rb
root to: 'tests#index'
app/views/tests/index.html.erb
<div class="max-w-sm mx-auto bg-white shadow-lg rounded-lg overflow-hidden">
  <div class="sm:flex sm:items-center px-6 py-4">
    <img class="block mx-auto sm:mx-0 sm:flex-shrink-0 h-16 sm:h-24 rounded-full" src="https://randomuser.me/api/portraits/women/17.jpg" alt="Woman's Face">
    <div class="mt-4 sm:mt-0 sm:ml-4 text-center sm:text-left">
      <p class="text-xl leading-tight">Erin Lindford</p>
      <p class="text-sm leading-tight text-gray-600">Customer Support Specialist</p>
      <div class="mt-4">
        <button class="text-purple-500 hover:text-white hover:bg-purple-500 border border-purple-500 text-xs font-semibold rounded-full px-4 py-1 leading-normal">Message</button>
      </div>
    </div>
  </div>
</div>

applyを使う

Tailwind CSSにはapplyという機能があり、複数のクラスをまとめて適用することができます。例えば同じボタンがあらゆる箇所に出現する場合、毎回font-bold py-2 px-4 rounded bg-red-500 text-white hover:bg-red-700などと書くのは大変なので、btnというクラスを指定するだけで上記のクラスを適用するためにapplyを使います。

【方法1】utilityの後に書く

この方法だと、widthのピクセル指定など、Tailwindのクラスでは表現できない部分のスタイルも指定できます。公式では、applyを使う場合utilityの前に書けと言われていますが、railsで使う場合utilityの後に書かないとうまく動作しませんでした。
※クラス名がユニークになるように気をつけてください。

app/javascript/css/tailwind.css
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
.btn {
  @apply font-bold py-2 px-4 rounded bg-red-500 text-white hover:bg-red-700;
  width: 300px;
}
app/views/tests/index.html.erb
<a href='#' class='btn'>ボタン</btn>

【方法2】helper関数で対応する

$ rails g helper tailwind
app/helpers/tailwind_helper.rb
module TailwindHelper
  def btn
    'fosnt-bold py-2 px-4 rounded bg-red-500 text-white hover:bg-red-700'
  end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  helper TailwindHelper
end
app/views/tests/index.html.erb
<a href='#' class='<%= btn %>'>ボタン</btn>

懸念点

TailwindCSSでは、想定されうるあらゆるユーティリティークラスが用意されているので、他のCSSフレームワークよりファイルサイズが大きいです。
この問題を、PurgeCSSという機能を使いビルド時に実際に使われているクラスに関するスタイルだけを抽出する方法で解決しています。

しかしRails上でTailwindを使う場合、PurgeCSSが使えません。(正確には設定方法がわかりません。分かる方がいたら教えてください。)
そのため通常よりファイルサイズが大きくなってしまいます。

解決しました↓↓↓

Purge CSS

使っているクラスのスタイルだけを抽出して、CSSのファイルサイズを軽くします。

$ yarn add @fullhuman/postcss-purgecss
postcss.config.js
let environment = { // 設定を変数にしまう
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    require('postcss-import'),
    require('postcss-flexbugs-fixes'),
    require('postcss-preset-env')({
      autoprefixer: {
        flexbox: 'no-2009'
      },
      stage: 3
    }),
  ]
}

// 使っているクラスだけを抽出する設定
if (process.env.RAILS_ENV === "production") {
  environment.plugins.push(
    require('@fullhuman/postcss-purgecss')({
      content: [
        './app/**/*.html.erb',
        './app/**/*.js.erb',
        './app/helpers/**/*.rb',
      ],
      defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
    })
  )
}

module.exports = environment // エクスポート

デプロイ前後で、本番環境以下のコマンドを叩き、ファイルサイズが小さくなっていることを確認

$ RAILS_ENV=production bin/webpack

Asset       Size
css/application-72aa1758.css   20.2 KiB
css/application-72aa1758.css.map   6.54 KiB
js/application-dbc0495e28056a133c61.js    844 KiB
js/application-dbc0495e28056a133c61.js.map    898 KiB
manifest.json  640 bytes         

デプロイ後にエラーが発生した場合の対処

CapistranoでVPSにデプロイしたところ、ブラウザからアクセスできなくなってしまいました。
log/production.logを確認したところ、以下のようなエラーメッセージが記録されていました。

ActionView::Template::Error (Webpacker can't find application in /var/www/html/namatsuba/releases/20200728115729/public/packs/manifest.json. Possible causes:
1. You want to set webpacker.yml value of compile to true for your environment
   unless you are using the `webpack -w` or the webpack-dev-server.
2. webpack has not yet re-run to reflect updates.
3. You have misconfigured Webpacker's config/webpacker.yml file.
4. Your webpack configuration is not creating a manifest.
Your manifest contains:
{
  "application.js": "/packs/js/application-b63d405284038a2c85dc.js",
  "application.js.map": "/packs/js/application-b63d405284038a2c85dc.js.map",
  "entrypoints": {
    "application": {
      "js": [
        "/packs/js/application-b63d405284038a2c85dc.js"
      ],
      "js.map": [
        "/packs/js/application-b63d405284038a2c85dc.js.map"
      ]
    }
  }
}
):

原因

config/webpacker.ymlを確認すると、デフォルトでは本番環境だけcssをextractする設定になっているようでした。
capistranoデプロイ時に実行されるrake assets:precompileRAILS_ENV=productionなしで実行されており、extract_cssがfalseの状態でprecompileされてしまっていたことが原因だったみたいです。

解決策

config/webpacker.ymlを以下のように修正して解決。

config/webpacker.yml
- extract_css: false
+ extract_css: true

//...
production:
  <<: *default
  compile: false
  extract_css: true

参考

22
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
d0ne1s
RailsとTailwindが好きなフリーランスエンジニア。 Qiitaの記事検索サービスqiigle.comを運営。 最近はAWSを勉強しなおしてます。 Twitterものぞいてくれるとうれしいです🦈
admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
22
Help us understand the problem. What is going on with this article?