Tailwind JIT使ってみた

はじめに

少し前から Tailwind JIT の存在は知っていましたが、次の動画を観ていませんでした。観たらちょっと感動しました。

Just-In-Time: The Next Generation of Tailwind CSS

Tailwind CSS を使うとPost CSSの処理によって、リリース版は10kBとかの小さなCSSサイズになり素晴らしいです。しかし、開発環境においては10MBを超えるような巨大なCSSを生成するため、DevToolsでデバッグする際の動作はもっさりします。また、ブラウザは20MBまでしか許容しないそうです。このTailwind CSSの制約を過去のものにして、さくさく開発できるのがTailwind CSSJust-in-Time (JIT)コンパイラです。これを使えば、僅かなコンパイラ時間後に、本番環境と同じCSSを使って開発を続けられるわけですね。

少し前に「Create React App プロジェクトにTailwind CSS入れてみた」(2021-05-05)という記事を書いたのですが、これを Tailwind JIT を使ったやり方で最初からやってみます。

ここで作ったプロジェクトはデプロイしていませんが、こちらと同じようなものです。

プロジェクトの生成

$ npx create-react-app プロジェクト名

インストール

npx create-react-app で生成済のプロジェクトにて、以下のコマンドを実行します。

$ npm install
$ npm install @tailwindcss/jit autoprefixer postcss tailwindcss -D
$ npm install postcss-cli
$ npm audit fix

フォルダ及びCSSファイルの追加

  1. src/styles フォルダを作成する
  2. src/styles/output.css を作成する(中身は空)
  3. 次の内容のsrc/styles/tailwind.css を作成する。
@tailwind base;
@tailwind components;
@tailwind utilities;

Create React App プロジェクトにTailwind CSS入れてみた」(2021-05-05)では、ここで次のようなCSSを指定していましたが、JITコンパイラを使う今回の方法ではここに書いたものはうまく変換されないようです。

.logo-height {
  height: 40vmin;
}

.header-font-size {
  font-size: calc(10px + 2vmin);
}

このため、代わりに src\App.js にて以下の形式で指定しました。

style={{fontSize: 'calc(10px + 2vmin)'}}

configファイルの追加

  • 以下のコマンドを実行します。
$ npx tailwindcss init -p
  • これで次の2つのファイルが生成されます。

tailwind.config.js

module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

tailwind.config.js の編集

ここでは、「Create React App プロジェクトにTailwind CSS入れてみた」(2021-05-05)とほぼ同じ以下の設定にしてみました。違いは、mode: “jit”が追加されているだけです。

module.exports = {

 mode: "jit",
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    backgroundColor: (theme) => ({
      ...theme('colors'),
      cra: '#282c34',
    }),
    textColor: (theme) => ({
      ...theme('colors'),
      reactBlue: '#61dafb',
    }),
    extend: {
      animation: {
        spinSlow: 'spinSlow infinite 20s linear',
      },
      keyframes: {
        spinSlow: {
          '0%': { transform: 'rotate(0deg)' },
          '100%': { transform: 'rotate(360deg)' },
        },
      },
    },
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

postcss.config.js の編集

次に変更します。

module.exports = {
  plugins: {
    "@tailwindcss/jit": {},
    autoprefixer: {},
  },
};

package.json の編集

scripts watch:css コマンドを追加します。

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject", // ★ 末尾のアポストロフィと次の行を追加

    "watch:css": "postcss -w src/styles/tailwind.css -o src/styles/output.css"
  },

index.css 及びその参照の削除

元々あった src\index.css は使わないので削除します。

また、それを src\index.js からインポートしている以下の行を削除します。

import './index.css';

App.js の暫定的な編集

ここでは、まず実験のため次の行を削除するかコメントアウトすることによって元のCSSが適用されなくなることを確認します。

import './App.css';

つぎに、Tailwind CSSを使えるようにするために、以下の行を追加します。

import './styles/output.css'

何でもよいので、Tailwind CSS を指定してみます。

function App() {
  return (
    <div className="App">
  ↓
   <div className="bg-purple-400">

npm run watch:css 及び npm run start の実行

npm run watch:css を実行することで、551行の src\styles\output.css が生成されました。

同時に npm run start が実行されていれば、背景色が淡い紫色になったのを確認できます。

とりあえずTailwind JIT が使用できた

この状態で、Tailwind CSS を追加したり、編集したりするとブラウザはホットリロードされます。

とりあえず、「Create React App プロジェクトにTailwind CSS入れてみた」(2021-05-05)と同じ状態にするために、@headlessui/react をインストールします。

$ npm install @headlessui/react
$ npm audit fix

App.js の最終的な編集

Create React App プロジェクトにTailwind CSS入れてみた」(2021-05-05)のコードと違う点は以下だけになります。

  1. index.css の代わりに、output.css をインポートしている
  2. index.css で追加していたCSSstyle属性で書くようにした(変換されないため)
  3. 表示するテキストの一部変更(前のプロジェクトと区別するため)
import { useState } from 'react';
import logo from './logo.svg';
import './App.css';
import './styles/output.css'
import { Switch } from '@headlessui/react';

function App() {
  const [useTailwind, setUseTaiwind] = useState(true);

  return (
    <>
      <Switch.Group>
        <div className='flex items-center'>
          <Switch.Label passive className='m-2'>
            Tailwind CSS (JITモード) を使用する
          </Switch.Label>
          <Switch
            checked={useTailwind}
            onChange={setUseTaiwind}
            className={`${
              useTailwind ? 'bg-green-500' : 'bg-gray-500'
            } relative inline-flex items-center h-6 rounded-full w-11 transition-colors focus:outline-none m-2`}
          >
            <span
              className={`${
                useTailwind ? 'translate-x-6' : 'translate-x-1'
              } inline-block w-4 h-4 transform bg-white rounded-full transition-transform`}
            />
          </Switch>
        </div>
      </Switch.Group>

      {useTailwind ? (
        // Tailswind CSS (src\styles\output.css 及び tailwind.config.js)を使用
        <div className='text-center'>
          <header
            className='flex flex-col items-center justify-center min-h-screen text-white bg-cra'
            style={{ fontSize: 'calc(10px + 2vmin)' }}
          >
            <img
              src={logo}
              className='pointer-events-none animate-spinSlow'
              style={{ height: '40vmin' }}
              alt='logo'
            />
            <p>
              <code>src\styles\output.css</code> 及び{' '}
              <code>tailwind.config.js</code> を使用
            </p>
            <a
              className='text-reactBlue'
              href='https://reactjs.org'
              target='_blank'
              rel='noopener noreferrer'
            >
              Tailwind CSS (JITモード) を使用しています
            </a>
            <p>
              ソースコードは
              <a
                className='text-reactBlue'
                href='https://github.com/pitang1965/cra-with-taiwindcss-jit'
                target='_blank'
                rel='noopener noreferrer'
              >
                こちら
              </a>
            </p>
          </header>
        </div>
      ) : (
        // src\App.css を使用
        <div className='App'>
          <header className='App-header'>
            <img src={logo} className='App-logo' alt='logo' />
            <p>
              <code>src\App.css</code> を使用
            </p>
            <a
              className='App-link'
              href='https://reactjs.org'
              target='_blank'
              rel='noopener noreferrer'
            >
              Tailwind CSSを使用していません
            </a>
            <p>
              ソースコードは
              <a
                className='text-reactBlue'
                href='https://github.com/pitang1965/cra-with-taiwindcss'
                target='_blank'
                rel='noopener noreferrer'
              >
                こちら
              </a>
            </p>
          </header>
        </div>
      )}
    </>
  );
}

export default App;

感想

  • 開発環境にて、「Create React App プロジェクトにTailwind CSS入れてみた」(2021-05-05)と今回のものを同時に起動し、それぞれをDevToolsの下記画面のチェックボックスのON/OFFを試すと明らかに反応時間が異なり、快適に作業できそうなことがわかりました。ただし、ドキュメント(Known limitations)に書かれているように、現状はまだ制限があるようです。
  • JITで使うのに、現状だと “npm run watch:css”と”npm run start”の両方を2つのターミナルなどから実行しないといけません。後者だけでできるように pakage.json を変更したほうがよさそうです。
DevToolsStylesでのチェックボックス