
# Mise en cache et minification

Trois enjeux de production se situent en périphérie du pipeline : éviter de recompiler une entrée identique, éviter le coût de création d’un compilateur à chaque requête et réduire la taille du CSS généré. Ces trois aspects sont des aides côté PHP autour du compilateur.

## Mise en cache

La génération de CSS exécute tout le pipeline à chaque appel. Pour le contenu qui ne change pas entre les requêtes, le cache basé sur des fichiers écrit le résultat sur disque et le sert lors des appels suivants.

Transmettez `cache` à `tw::generate()` — `true` pour le répertoire par défaut, ou une chaîne de chemin pour en choisir un autre :

```php
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
]);
```

Le répertoire de cache est créé automatiquement s’il n’existe pas.

### Clé de cache

La clé est calculée à partir du **contenu**, de la **configuration CSS** et de l’indicateur **minify**, puis hachée pour former le nom du fichier `tailwind_<hash>.css`. Toute modification du balisage, de l’entrée CSS ou de l’activation de la minification produit une clé différente, et donc un fichier différent.

La configuration CSS incluse dans la clé correspond à la configuration `css` intégrée, plus le contenu des fichiers indiqués dans `importPaths`. Deux entrées n’en font pas partie : les fichiers inclus par un `@import` imbriqué dans ces fichiers et la version de TailwindPHP. Videz le cache après avoir modifié un import imbriqué ou mis à niveau le paquet, sinon l’ancienne sortie continuera d’être servie.

### Durée de vie

`cacheTtl` désigne une durée de vie en secondes. Lors d’un accès au cache, l’heure de modification du fichier est comparée à l’heure actuelle ; si le fichier date de plus de `cacheTtl`, le cache est considéré comme manquant et le fichier est recompilé. Sans `cacheTtl`, les entrées n’expirent jamais : supprimez-les explicitement.

### Vider le cache

`tw::clearCache()` (ou la fonction `clearCache()`) supprime les fichiers `tailwind_*.css` d’un répertoire de cache et renvoie le nombre de fichiers supprimés.

```php
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
```

## Cache de l’état du compilateur

Le cache de sortie n’est utile que si le même contenu revient. Lorsque le contenu change à chaque appel, la partie coûteuse est la création du compilateur lui-même : résolution de `@import "tailwindcss"`, analyse des ressources intégrées et accumulation du thème. Cette phase ne dépend que de l’entrée CSS ; elle peut donc être stockée et réutilisée.

Transmettez `stateCacheFile` à `tw::compile()` (ou à `new TailwindCompiler($css, $options)`) :

```php
use TailwindPHP\tw;

$compiler = tw::compile($themeCss, [
    'stateCacheFile' => __DIR__ . '/cache/tailwind-state.php',
]);

$css = $compiler->generateExact($html, true);
```

Lors de la première création, l’état est enregistré à cet emplacement dans un fichier PHP brut, que OPcache peut partager entre les requêtes ; les créations suivantes le chargent au lieu de procéder à une nouvelle analyse. La sortie est identique octet pour octet à celle d’un compilateur sans cache.

- Le fichier est validé à l’aide d’une empreinte du moteur (taille et date de modification des sources et ressources de TailwindPHP), d’une clé calculée à partir de l’entrée CSS et des options `base` et `importSearchPaths`, ainsi que de la taille et de la date de modification de chaque fichier importé par l’entrée. En cas de différence, le fichier est reconstruit et réécrit : la mise à niveau de TailwindPHP ou la modification d’un fichier importé ne nécessite aucune intervention manuelle.
- Le chemin vous appartient : utilisez un fichier par entrée CSS distincte, dans un répertoire accessible en écriture pour le serveur Web. Les écritures sont atomiques (fichier temporaire puis `rename()`).
- Les entrées qui utilisent un `importResolver` personnalisé contournent le cache, car le comportement du résolveur ne peut pas être associé à une empreinte.
- Le même cache est disponible autour du tableau `compile()` de bas niveau API sous la forme `TailwindPHP\StateCache\compileCssCached($css, $cacheFile, $options)`.

`tw::generate()` n’accepte pas `stateCacheFile` ; il crée un nouveau compilateur à chaque appel. Utilisez une instance de compilateur si le coût de création est important.

## Minification

La minification réduit la taille de la sortie pour la production. L’indicateur `minify` produit directement du CSS minifié pendant la sérialisation ; c’est donc la méthode la plus rapide et la plus précise. `tw::minify()` exécute le minificateur basé sur les chaînes (`src/_tailwindphp/CssMinifier.php`) sur une chaîne CSS existante :

```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);
```

Les deux méthodes produisent une structure équivalente, mais pas des octets identiques. La méthode du sérialiseur préserve les sélecteurs `:not()` descendants que la passe sur les chaînes regroupe. Préférez donc l’indicateur `minify` pour la sortie générée et réservez `tw::minify()` au CSS fourni sous forme de chaîne.

### Fonctionnement

Les deux méthodes appliquent les mêmes réductions de taille :

| Étape | Effet |
|------|--------|
| Suppression des commentaires | Supprime les blocs `/* … */` |
| Réduction des espaces | Réduit les suites d’espaces et les supprime autour de `{ } ; : ,` et des combinateurs de sélecteurs |
| Raccourcissement des couleurs hexadécimales | `#ffffff` → `#fff`, `#aabbcc` → `#abc` |
| Suppression des unités de zéro | `0px` → `0` (préserve les valeurs temporelles `0s`/`0ms`) |
| Raccourcissement de font-weight | `font-weight:normal` → `400`, `font-weight:bold` → `700` |
| Suppression des règles vides | Supprime les sélecteurs dont les blocs de déclarations sont vides |

Par conception, la minification ne fusionne pas les sélecteurs en double ni les propriétés abrégées : cela compliquerait le débogage et pourrait affecter la cascade.

### CLI : `--minify` ou `--optimize`

La [CLI](https://tailwindphp.inline0.dev/fr/docs/cli) expose la méthode de minification du sérialiseur au moyen de deux indicateurs :

```bash
# 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
```

Dans la version actuelle, `--optimize` minifie également la sortie : les deux commandes écrivent donc les mêmes octets ([#9](https://github.com/inline0/tailwindphp/issues/9)). Les transformations équivalentes à lightningcss sont exécutées à chaque compilation ; la sortie sans indicateur est donc déjà optimisée et lisible.

Pour le reste de l’API publique — `tw::generate()`, `tw::compile()`, méthodes d’inspection et formats d’entrée — consultez la [référence API](https://tailwindphp.inline0.dev/fr/docs/api).
