TailwindCSS & PurgeCSS で高速化

TailwindCSS と PurgeCSS を組み合わせると、無駄のないCSSを生成することができ、高速化が図れます。

TailwindCSS

TailwindCSS (テールウインドCSS)は「ユーティリティファースト」を掲げるCSSです。

他のCSSフレームワークがコンポーネント(機能を含むパーツ)中心のものが多いのに対し、TailwindCSSはユーティリティ(効果・状態)に主眼を置いています。

例えば Bootstrap は「アラート」や「カード」といったパーツごとのクラス名が揃っており、コードをコピペすればすぐに使えます。

対して TailwindCSS の場合、「横マージンが5」「ボーダー色が青50%」といった効果や状態を表すクラス名が主で、これを組み合わせて使うようにできています。

どちらが良いということはなく、状況によって使い分けできると良いと思います。

PurgeCSS

PurgeCSS (パージCSS)は、HTMLなどのファイルを解析し、使われていないCSSクラスを除去(パージ)してコンパイルする nodejs 用のツールです。

CSSフレームワークを使ったうえで、サイトで使用していないクラスを削除してみると、驚くほど使っていない機能があることがわかります。

そういった無駄を省き、サイトを高速化できるツールです。

Laravel Mixでの利用

TailwindCSS 、PurgeCSS とも単体( Webpack など)での利用もできますが、弊社では Laravel を使うことが多いのもあり、Larave Mix を通した利用方法を紹介します。
Laravel(PHP)でないサイトでも使えますが、 PurgeCSS の対象ディレクトリの指定などが必要です。

必要なライブラリをインストール

TailwindCSS、Laravel Mix と、必要なライブラリを含めてインストールします。(カッコン内は執筆時点のバージョン)

npm install --save-dev tailwindcss laravel-mix laravel-mix-tailwind laravel-mix-purgecss cross-env

プロジェクトルートに tailwind.js がなければ作成します。

// デフォルトの設定内容を読み込み
const config = require('tailwindcss/defaultConfig');

// ひとまず設定なし
module.exports = {
  theme: {},
  variants: {},
  plugins: []
};

プロジェクトルートに webpack.mix.js がなければ作成します。

const mix = require('laravel-mix');

// ライブラリ読み込み
require('laravel-mix-tailwind');
require('laravel-mix-purgecss');

mix
  .js('resources/js/app.js', 'public/js')
  .sass('resources/sass/app.scss', 'public/css');

// TailwindCSS適用
mix.tailwind();

// PurgeCSS適用
mix.purgeCss({
  // production時のみ有効化
  enabled: mix.inProduction()
});

PurgeCSS対象ディレクトリの指定

プロジェクトがLaravelでなければ、以下のように対象ディレクトリ(対象ファイル)の指定が必要です。

const mix = require('laravel-mix');
const path= require('path');

...

// PurgeCSS適用
mix.purgeCss({
  // production時のみ有効化
  enabled: mix.inProduction(),

  globs: [
    path.join(__dirname, 'public/**/*.html'),
    path.join(__dirname, 'public/assets/**/*.js')
  ]
});

上記で glob 部分はデフォルト設定(Laravel向けの設定)にマージされますが、上書きしたい場合は公式ヘルプの方法で可能です。

コマンド登録

package.json にコマンドを登録しておくと、呼び出しが楽になります。
Laravel プロジェクトの場合は、すでに登録されているはずです。

{
    ...

    "scripts": {
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",

        "watch": "npm run development -- --watch",

        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },

    ...
}

コーディング

HTMLやPHPで、TailwindCSSを用いてコーディングします。

例えば以下のようなコードがあるとします。
横4rem、縦4remで円形にした画像という指定です。

<img class="h-16 w-16 rounded-full mx-auto" src="avatar.jpg">

PurgeCSSは、ファイルをスキャンして上記のようなクラス名部分を読み取り、使用しているもののみコンパイルします。

クラス名をプログラムで出力している場合、PurgeCSSが読み取れないものもあります。

そういった場合は PurdeCSS の設定に記述します。

const mix = require('laravel-mix');

...

// PurgeCSS適用
mix.purgeCss({
  // production時のみ有効化
  enabled: mix.inProduction(),

  // 単数で指定されている要素の場合(.target, #name, buttonなどが該当)
  whitelist: ['target', 'name', 'button'],

  // 複数指定の一部ならパターンで指定
  whitelistPatterns: [/target/, /btn/],

  // 子クラス名(.target-blueなど)
  whitelistPatternsChildren: [/blue$/],
});

ホワイトリスト設定について、詳しくは公式ヘルプを参照してください。

ベースとなるCSSに以下の記述が必要です。

@tailwind base;
@tailwind components;
@tailwind utilities;

tailwindcss ライブラリをインストールしたことにより @tailwind というディレクティブが使用できます。

上記の記述で、TailwindCSS の全機能が読み込まれます。
最終的に、 PurgeCSS がこの全機能+自前CSSから余分なものを削除します。

コンパイル

以下のコマンドでCSSをコンパイルしてみます。

npm run production

webpack.mix.js にて production 時のみコンパイルするよう指定したので、上記のコマンドで PurgeCSS が動作します。

コンパイル後は、おそらくかなり少なくなると思います。
場合によっては、外部ファイルではなくHTML内に直接書ける(PHPで include するなど)くらいの量になります。
そうなると余計なHTTPリクエストが減り、 PageSpeed Insights で、かなりの高得点が出る可能性があります。

昨今は React や Vue などで細かくコンポーネント化できる場面も増え、CSS側でパーツごとのレイアウトを決める必要がない場面が増えてきました。
そうなると、CSSは TailwindCSS のように効果や状態のみを管理できれば十分なのかもしれません。