キャッシュと圧縮
本番環境では、パイプラインの最後にある3つの課題に対処します。同じ入力の再コンパイルを避けること、リクエストごとのコンパイラー構築コストを避けること、生成されたCSSを縮小することです。いずれもコンパイラーを囲むPHP側のヘルパーです。
キャッシュ
CSSの生成では、呼び出すたびにパイプライン全体を実行します。リクエスト間で内容が変わらない場合、ファイルベースのキャッシュが結果をディスクに書き込み、以降の呼び出しではその結果を返します。
cacheをtw::generate()に渡します。デフォルトのディレクトリを使う場合はtrue、独自のディレクトリを使う場合はパス文字列を指定します。
use TailwindPHP\tw;
// Cache to the default directory: sys_get_temp_dir() . '/tailwindphp'
$css = tw::generate([
'content' => '<div class="flex p-4">Hello</div>',
'cache' => true,
]);
// Cache to a custom directory
$css = tw::generate([
'content' => '<div class="flex p-4">Hello</div>',
'cache' => '/path/to/cache',
]);
// With a time-to-live (seconds)
$css = tw::generate([
'content' => '<div class="flex p-4">Hello</div>',
'cache' => true,
'cacheTtl' => 3600, // expire after 1 hour
]);
キャッシュディレクトリが存在しない場合は、自動的に作成されます。
キャッシュキー
キーはコンテンツ、CSS設定、minifyフラグから生成され、ファイル名tailwind_<hash>.cssにハッシュ化されます。マークアップ、CSS入力、またはミニファイの有効・無効のいずれかが変わると、キーが変わり、別のファイルが使われます。
キーに含まれるCSS設定は、インラインのcssと、importPathsで指定されたファイルの内容です。キーに含まれない入力が2つあります。これらのファイル内のネストされた@importで読み込まれるファイルと、TailwindPHPのバージョンです。ネストされたインポートを編集した後やパッケージをアップグレードした後はキャッシュを消去してください。そうしないと、古い出力が返され続けます。
有効期限
cacheTtlは秒単位の有効期間です。キャッシュにヒットすると、ファイルの更新時刻を現在時刻と比較します。ファイルがcacheTtlより古ければ、キャッシュミスとして扱い再コンパイルします。cacheTtlを指定しない場合、エントリーは期限切れにならないため、明示的に消去してください。
キャッシュの消去
tw::clearCache()(またはclearCache()関数)は、キャッシュディレクトリ内のtailwind_*.cssファイルを削除し、削除したファイル数を返します。
use TailwindPHP\tw;
use function TailwindPHP\clearCache;
$deleted = tw::clearCache(); // default directory
$deleted = tw::clearCache('/path/to/cache'); // custom directory
clearCache('/path/to/cache'); // function form
コンパイラー状態キャッシュ
出力キャッシュが役立つのは、同じコンテンツが再び使われる場合だけです。呼び出しごとに内容が変わる場合、コストがかかるのはコンパイラー自体の構築です。@import "tailwindcss"の解決、バンドルされたリソースの解析、テーマの蓄積が含まれます。この処理は入力CSSだけに依存するため、保存して再利用できます。
stateCacheFileをtw::compile()(またはnew TailwindCompiler($css, $options))に渡します。
use TailwindPHP\tw;
$compiler = tw::compile($themeCss, [
'stateCacheFile' => __DIR__ . '/cache/tailwind-state.php',
]);
$css = $compiler->generateExact($html, true);
初回の構築時に、状態は通常のPHPファイルとしてそのパスに書き込まれます。OPcacheはこれをリクエスト間で共有できます。以降の構築では再解析せずに読み込みます。出力はキャッシュを使わないコンパイラーとバイト単位で同一です。
- ファイルはエンジンのフィンガープリント(TailwindPHPのソースとリソースのサイズおよび更新時刻)、入力CSSと
baseおよびimportSearchPathsオプションから生成したキー、入力がインポートした各ファイルのサイズと更新時刻に照らして検証されます。不一致があれば再構築して書き換えるため、TailwindPHPのアップグレードやインポート先ファイルの編集に手動作業は不要です。 - パスは利用者が管理します。入力CSSごとに1つのファイルを使い、ウェブサーバーが書き込めるディレクトリに配置してください。書き込みは一時ファイルと
rename()を使ってアトミックに行われます。 - カスタム
importResolverを使う入力は、リゾルバーの動作をフィンガープリント化できないため、キャッシュを迂回します。 - 同じキャッシュは、低レベルの
compile()配列APIのTailwindPHP\StateCache\compileCssCached($css, $cacheFile, $options)としても利用できます。
tw::generate()はstateCacheFileを受け取らず、呼び出すたびに新しいコンパイラーを構築します。構築コストが問題になる場合は、コンパイラーのインスタンスを使ってください。
圧縮
ミニファイは本番環境向けに出力を縮小します。minifyフラグはシリアライズ時にミニファイ済みCSSを直接出力するため、最速かつ最も正確な方法です。tw::minify()は既存のCSS文字列に対して、文字列ベースのミニファイア(src/_tailwindphp/CssMinifier.php)を実行します。
use TailwindPHP\tw;
// Minify during generation (serializer path, preferred)
$css = tw::generate([
'content' => '<div class="flex p-4">Hello</div>',
'minify' => true,
]);
// Or minify an existing string (string-based post-pass)
$css = tw::generate('<div class="flex p-4">Hello</div>');
$minified = tw::minify($css);
2つの方法で得られる構造は同等ですが、バイト列は同一ではありません。シリアライザー方式では、文字列処理方式がまとめてしまう子孫:not()セレクターが保持されます。そのため、生成する出力にはminifyフラグを使い、文字列として渡されるCSSにはtw::minify()を使ってください。
処理内容
どちらの方法でも、同じサイズ削減処理を適用します。
| 手順 | 効果 |
|---|---|
| コメントの削除 | /* … */ブロックを取り除きます |
| 空白の圧縮 | 連続する空白をまとめ、{ } ; : ,やセレクターの結合子の前後から空白を取り除きます |
| 16進数カラーの短縮 | #ffffff → #fff、#aabbcc → #abc |
| ゼロ単位の削除 | 0px → 0(0s/0msの時間値は保持) |
| font-weightの短縮 | font-weight:normal → 400、font-weight:bold → 700 |
| 空ルールの削除 | 宣言ブロックが空のセレクターを削除します |
設計上、重複セレクターの統合やショートハンドプロパティの結合は行いません。どちらもデバッグを難しくし、カスケードに影響する可能性があるためです。
CLI:--minifyと--optimizeの比較
CLIでは、2つのフラグを使ってシリアライザーのミニファイ経路を利用できます。
# Optimize and minify (smallest output)
tailwindphp -i ./src/app.css -o ./dist/styles.css --minify # or -m
# Meant to optimize without minifying
tailwindphp -i ./src/app.css -o ./dist/styles.css --optimize
現行リリースでは--optimizeもミニファイを行うため、どちらのコマンドも同じバイト列を書き出します(#9)。lightningcss相当の変換はどちらの場合もビルドごとに実行されるため、フラグなしの通常出力もすでに最適化された読みやすい形式です。
その他の公開API(tw::generate()、tw::compile()、検査メソッド、入力形式)については、APIリファレンスを参照してください。