CSS Purge
CSS Purge は、ビルド出力をスキャンして実際に使われている Lism CSS クラスだけを残す仕組みです。Vite / Astro 向けのプラグインは @lism-css/plugin パッケージで提供しています。
CSS Purge は、ビルド出力の HTML / JS に完全な文字列として現れるクラスだけを検出できます。SPAや Astro のclient:onlyなど、クライアント側で生成するprops由来のクラスは、静的な値でも自動検出の対象外です。有効にする前に、対応範囲と制約を確認してください。
pnpm add -D @lism-css/plugin推奨セットアップ(統合プラグインを使う)
@lism-css/plugin の統合プラグインを使っている場合は、purge: true オプションを渡すだけで有効化できます。
import { defineConfig } from 'astro/config';import { lismCss } from '@lism-css/plugin/astro';
export default defineConfig({ integrations: [lismCss({ purge: true })],});import { defineConfig } from 'vite';import { lismCss } from '@lism-css/plugin/vite';
export default defineConfig({ plugins: [lismCss({ purge: true })],});オブジェクトで渡すと、CSS Purge の各オプションも指定できます。
lismCss({ purge: { report: true, // ビルドログに CSS Purge 前後のサイズを出力 safelist: ['-p:30'], // 静的解析で検出されないクラスを残す },});単体プラグイン(@lism-css/plugin/purge/vite の lismPurge / @lism-css/plugin/purge/astro の lismPurgeAstro)を直接 import して使うこともできます。
仕組み
ビルド時に出力された HTML / JS から、Lism CSS の命名規則(c-- / a-- / l-- / is-- / has-- / set-- / u-- プレフィックス、および -prop:value 形式の Property Class)にマッチするクラス名を収集します。その後、CSS ファイルをパースして、使われているクラスに紐づくセレクタのみを残します。
- 対象は、上記の命名規則に合うセレクタを含む CSS のみ(含まない CSS はそのまま出力)
- ユーザー定義のクラスや他ライブラリの CSS は変更しない
:not()/:has()の中に書かれたクラスは、「使われているクラス」としては数えません[class*="-p:"]のような属性セレクタは、使われているクラスや safelist に一致するものを残します
対応範囲と制約
React / Astro コンポーネントのpropsは、実行時にクラス名へ変換されます。例えば<Box p="20">は-p:20を出力しますが、クライアントJSにはp: "20"しか残らない場合があります。propsの値が静的でも、完全なクラス名がビルド出力に存在しなければ、対応するCSSは削除されます。
| 構成・ケース | 検出できる範囲 |
|---|---|
| Astro SSG(prerender) | 最終HTMLに出力されたクラスを検出できます |
| SPA(Vite + Reactなど) | CSR領域のprops由来のクラスは自動検出できません |
Astro のclient:only |
初期HTMLにレンダー結果がないため、props由来のクラスは自動検出できません |
| ハイドレーション後にpropsの値が変わる場合 | 初期HTMLにもJSの完全文字列にも現れないクラスは検出できません |
| SSRオンデマンドページ | serverチャンクに完全な文字列として存在するクラスのみ検出できます。リクエスト時にpropsから組み立てるクラスは検出できません |
| Next.js | CSS Purge プラグインは未提供です(統合プラグインのCSSビルド機能のみ対応) |
例えば<Box p={isOpen ? 20 : 40}>で、ビルド時に20側だけがHTMLに出力される場合、40側の-p:40は、他のビルド出力にも完全文字列がなければ保持されません。こうした領域で使うクラスは、必要なクラス全体をsafelistで保持してください。列挙やクラス系統の指定が難しい場合は、統合プラグインのpurgeを省略するかfalseにする、または単体purgeプラグインを外して無効にしてください。
ビルド時には、次の条件で警告を表示します。
- Astro 版: 出力HTMLに
client:onlyアイランドがある場合 - Vite 版: クライアントJSチャンクに Lism のランタイムが含まれ、HTMLから Lism クラスを1つも検出できない場合
警告はsafelist指定済みでも表示します。設定の有無だけでは必要なクラスがすべて保護されているか判断できないためです。また、この警告ですべての未検出クラスを検知できるわけではなく、警告が出なくてもprops由来のクラスが保持される保証はありません。
単体プラグインを直接使う場合
統合プラグインを使わずに、単体プラグインを Vite / Astro の設定ファイルに追加することもできます。
import { defineConfig } from 'vite';import { lismPurge } from '@lism-css/plugin/purge/vite';
export default defineConfig({ plugins: [lismPurge()],});import { defineConfig } from 'astro/config';import { lismPurgeAstro } from '@lism-css/plugin/purge/astro';
export default defineConfig({ integrations: [lismPurgeAstro()],});Vite プラグインは apply: 'build' / enforce: 'post' で動作するため、開発サーバー (vite dev) では何も実行されません。vite build 実行時のみ、生成された CSS から未使用セレクタが削除されます。Astro 用は astro:build:done フックで、ビルド出力配下の HTML / JS をスキャンし、CSS ファイルを書き換えます。
SSR / hybrid 構成(output: 'server'、または prerender = false のルートがある場合)では、client 出力(dist/client/)に加えて server 出力(dist/server/)もスキャンと参照書き換えの対象になります。オンデマンドページだけで使うクラスも、serverチャンクに完全な文字列として存在すれば保持されます。propsから実行時に組み立てるクラスには、対応範囲と制約の対策が必要です。
full.css と組み合わせる
lism-css/full.css は、main.css には含まれないブレイクポイント対応クラスやカラートークンのクラスまで収録した全部入りビルドです(収録内容は CSSファイルの種類 を参照)。素のまま読み込むとサイズが大きいため、CSS Purge との併用を前提にした配布物です。
// main.css の代わりに full.css を読み込むimport 'lism-css/full.css';CSS Purge を有効にしたうえで full.css に切り替えると、main.css には含まれないトークンクラスや拡張ブレイクポイントが使えるようになり、かつ最終的な CSS はサイト全体で実際に使われているクラスだけに絞り込まれます。
CSS Purge を使わずに full.css を読み込むと、未使用クラスを含む大きな CSS がそのまま配信されます。full.css は必ず CSS Purge と併用してください。
オプション
統合プラグインの purge オプションでも、単体プラグインでも、同じ LismPurgeOptions を渡せます。
| オプション | 説明 |
|---|---|
safelist |
静的解析で検出されないクラスを残す |
report |
ビルドログに CSS Purge 前後のファイルサイズを出力 |
known |
CSS Purge が「Lism のクラス」として扱う一覧を差し替える(通常は指定不要) |
safelist
JS で動的に組み立てるクラス名など、ビルド出力に文字列として現れないクラスは静的解析で検出できません。誤って削除されるのを防ぐには safelist に追加します。
lismPurge({ safelist: [ // 文字列で完全一致 '-p:30', // 正規表現でマッチ /^-bgc:/, // 関数で判定 (className) => className.startsWith('-fz:'), ],});string エントリは属性セレクタ([class*="..."] など)の照合にも使われます。RegExp / 関数のエントリはクラス名を列挙できないため属性セレクタと照合できず、これらが1つでもあると、使われているクラスや string エントリに一致しなかった属性セレクタはすべて残されます。
report
true にすると、CSS Purge 前後の合計バイト数と削減率がビルドログに出力されます。
CSS: 28100 → 13200 bytes (-14900 / -53.0%)known
CSS Purge が「Lism のクラス」として扱う一覧です。指定しない場合、ビルド開始時に lism.config.js を反映した full.css から自動で作られます。そのため、lism.config.js で追加した prop / トークン由来のクラスも、未使用なら正しく削除されます。full.css は main.css のセレクタをすべて含むので、どちらを読み込んでいても取りこぼしはありません。関数を渡すと、ビルド時にその関数が呼ばれ、戻り値が一覧として使われます。
注意事項
- クラス名を切り替える場合は、
size === 'l' ? '-p:40' : '-p:30'のように完全な文字列で書いてください。テンプレートリテラルの`-p:${size}`や'-p:' + sizeでは、完全なクラス名を検出できません。それが難しいときはsafelistに追加してください。 - CSS Purge はビルド出力全体のどこかで使われているクラスをすべて残します(ページ単位ではありません)。あるページで使っていなくても、サイト内のどこかのページで使われていれば残されます。これは複数ページで共有される CSS を壊さないための挙動です。
- CSS Purge の対象は Lism CSS が出力した CSS に限定されます。自前で書いた CSS や他ライブラリの CSS は変更されません。
- Tailwind CSS など、別のフレームワークの未使用クラス削除機能とは独立して動作します。
- CSS の sourcemap には対応していません。CSS Purge はルールを削除するため、既存の sourcemap とは行がずれます。誤った sourcemap を参照しないよう、CSS Purge 適用後の CSS から
sourceMappingURLコメントを削除し、古い.css.mapも削除します。CSS の sourcemap が必要な場合は CSS Purge を無効にしてください。 - Vite 版では、CSS Purge によって CSS ファイル名(内容ハッシュ)が変わっても、その CSS を参照する JS チャンク自体のファイル名は再計算されません(チャンク名は CSS Purge の処理より前に確定しているためです)。チャンクの中身は新しい CSS 名に書き換えられますが、ファイル名は変わらないため、ファイル名ベースの immutable キャッシュを行う CDN 等では、過去のデプロイでキャッシュされた古いチャンクが配信され続けると、存在しない旧 CSS 名を参照して 404 になる可能性があります。該当する環境では、デプロイ時に CDN のキャッシュを無効化してください。
- CSS Purge の対象となる CSS は、ファイル名の末尾セグメントがちょうど 8 文字の英数字の場合(
<name>.xxxxxxxx.css、Vite 版では<name>-xxxxxxxx.cssも対象)にハッシュ付きファイル名とみなされ、CSS Purge 適用後の内容に基づくハッシュへリネームされます。app-critical.cssのようにハッシュではない名前もこのパターンに一致するため、ビルド出力の CSS を外部から固定ファイル名で直接参照する場合は、末尾セグメントがちょうど 8 文字の英数字になる名前を避けてください。