🙃

Rails+Tailwind Production環境で一部cssが反映されない問題の解決法

2021/05/30に公開

はじめに

Tailwindを使用しており本番用にPurgeCSSでアセットの容量を軽くできたのはいいが、一部のcssが反映されていないという状況を解決します。

purgeCSSを利用するための準備

tailwindを含めて、purgeCSSを使用するために必要なpackageは以下となります。

# package.json
{
  "name": "my_app",
  "private": true,
  "dependencies": {
    "@fullhuman/postcss-purgecss": "^3.0.0",
    "autoprefixer": "^9.8.6",
    "postcss": "^7.0.35",
    "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.1.2",
  },
  "version": "0.1.0",
  "devDependencies": {
  }
}

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',
      ],
      # ここが重要
      safelist: ['a', 'open'],
      defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
    })
  )
}

module.exports = environment

PurgeCSSでは対象となるファイル内の要素やクラス名に使用されるCSS意外を全て切り捨てることでアセットの容量を軽くすることが可能となります。
ここでの対象となるファイルとは上記のcontentで指定しているとおり、コンパイル後のhtmlなどではなくテンプレートエンジンでの記述そのものが対象となるので注意が必要です。
例えば、railsの場合リンクを作る際はaではなくlink_toが使用されるため、aに関するcssは除外されてしまいます。(例:normalize.cssのリンク部分など)
また、jsなどにより動的に付加されるクラス名に関するcssも除外されます。それを避けるためにはsafelistで個別にセレクタを指定してあげることが必要となります。

Discussion