Svelte + Vite環境のサイトのTailwindCSSをv4にアップグレードした話と@applyへの考え方の変化
はじめに
先日、Tailwind CSSのv4がリリースされた。
自分のポートフォリオサイトがSvelte(厳密にはSvelteKit) + Vite構成でTailwind CSSを使っているので試しにアップグレードしてみた。その手順と、その際に変化した@apply
に対する考え方について残しておく。
アップグレード手順
アップグレードガイドが用意されているので、基本的にそれを見ながら進めていく。Deprecatedになったものや名前が変わったユーティリティもあるので注意。
まずは公式で用意しているアップグレードツールを実行した。これを実行すると、tailwind.config.js
が削除され、app.css
が更新された。
npx @tailwindcss/upgrade@next
これだけでは足りないので、以下を参考にして必要な対応を続ける。
npm install @tailwindcss/vite
をして必要なプラグインをインストールし、vite.config.ts
にプラグインとして追加する。
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite'; // 追加
export default defineConfig({
plugins: [
sveltekit(),
tailwindcss(), // 追加
],
})
本来であればこれで動くはずだった。
@applyへの対応
しかし、npm run dev
して開発サーバーを起動してみるとError: Cannot apply unknown utility class
というエラーが出た。アップグレードガイドをよく見ると、CSSモジュールファイルや、SvelteやVueの<style>
ブロック内で@apply
を使っている場合は、@reference
で@import "tailwindcss";
のあるCSSファイルを読み込む必要があるらしい。
v4からはメインのCSSファイルとは別にバンドルされるスタイルシートから、Tailwindのテーマ変数、カスタムユーティリティ、カスタムバリアントが参照できなくなった。そのため、これらを使用する場合は、@reference
を使ってメインのCSSファイルを明示的に参照する必要があるようだ。
例えば、以下のように@reference
を使うことで今までと同様に@apply
を使うことができる。
<div class="text-class">
<p>text</p>
</div>
<style>
@reference "../../styles/app.css";
.text-class {
@apply p-2;
}
</style>
@applyに対する考え方の変化
今まで自分は、@apply
を使うことでTailwindのユーティリティをまとめられ、スタイルの機能を分かりやすくできると考えて使っていた。しかし、今回の変更から毎回@reference
を書くのは面倒だと思い、改めて@apply
について調べてみた。
その結果、@apply
を使うのは今後は控えようと思った。理由としては、適切な粒度にコンポーネントを作成できていれば@apply
は不要だと感じたため。公式ドキュメントの以下を読んで特にそう感じた。何より、Tailwind作者の@adamwathan氏が@apply
の使うよりもプレーンなTailwind変数を使うことを推奨しているのも大きい。長いものには巻かれろの精神。
また、調べる中で作者以外にも@apply
の使用は控えた方が良いという方をいくつか見かけた。理由としてはクラスの命名やCSSのグローバルスコープ、バンドルサイズの増加があったが、SvelteのようなSingleFileComponentでは命名やスコープに不便を感じることは少ないし、バンドルサイズの増加も自分のサイトほどの規模では目くじらを立てるほどのサイズ増ではなかった。とはいえ、そういったデメリットを今の小さなSvelteのサイトでは感じていないだけで、他のアプリケーションでは問題として発生しうる。そうであれば@apply
に頼らない使い方に慣れておいた方が良いだろう、というのも使用を控えようと思った理由の一つだ。
おわり
色々あったがポートフォリオサイトをTailwindCSSのv4にアップグレードすることができた。今後は@apply
に頼らず、コンポーネントの分割や適切なprops設計を意識しながらスタイルを管理していきたい。