
# Caching und Minifizierung

Drei Aufgaben für den Produktionseinsatz liegen am Rand der Pipeline: identische Eingaben nicht erneut kompilieren, den Compiler nicht bei jeder Anfrage neu erstellen und das generierte CSS verkleinern. Alle drei werden durch Hilfsfunktionen auf PHP-Seite ergänzt.

## Caching

CSS wird bei jedem Aufruf durch die gesamte Pipeline geleitet. Bei Inhalten, die sich zwischen Anfragen nicht ändern, schreibt der dateibasierte Cache das Ergebnis auf die Festplatte und liefert es bei späteren Aufrufen von dort.

Übergib `cache` an `tw::generate()` – `true` für das Standardverzeichnis oder einen Pfadstring für ein eigenes Verzeichnis:

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

Das Cache-Verzeichnis wird automatisch erstellt, falls es noch nicht existiert.

### Cache-Schlüssel

Der Schlüssel wird aus dem **Inhalt**, der **CSS-Konfiguration** und dem **minify**-Flag abgeleitet und in den Dateinamen `tailwind_<hash>.css` gehasht. Jede Änderung am Markup, an der CSS-Eingabe oder daran, ob Minifizierung aktiviert ist, ergibt einen anderen Schlüssel und damit eine andere Datei.

Die CSS-Konfiguration im Schlüssel umfasst die Inline-`css` sowie den Inhalt der in `importPaths` genannten Dateien. Zwei Eingaben sind nicht darin enthalten: Dateien, die über ein verschachteltes `@import` in diesen Dateien eingebunden werden, und die TailwindPHP-Version. Leere den Cache nach Änderungen an einem verschachtelten Import oder nach einem Paket-Upgrade, sonst wird weiterhin die alte Ausgabe bereitgestellt.

### Gültigkeitsdauer

`cacheTtl` gibt die Lebensdauer in Sekunden an. Bei einem Cache-Treffer wird die Änderungszeit der Datei mit der aktuellen Zeit verglichen. Ist die Datei älter als `cacheTtl`, gilt der Treffer als veraltet und der Inhalt wird neu kompiliert. Ohne `cacheTtl` laufen Einträge nie ab – leere den Cache manuell.

### Cache leeren

`tw::clearCache()` (oder die Funktion `clearCache()`) entfernt die `tailwind_*.css`-Dateien aus einem Cache-Verzeichnis und gibt die Anzahl der gelöschten Dateien zurück.

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

## Compiler-Statuscache

Der Ausgabecache hilft nur, wenn derselbe Inhalt erneut aufgerufen wird. Ändert sich der Inhalt bei jedem Aufruf, ist das Erstellen des Compilers selbst der kostspielige Teil: `@import "tailwindcss"` auflösen, die gebündelten Ressourcen parsen und das Theme zusammenstellen. Dieser Schritt hängt nur von der Eingabe-CSS ab und kann deshalb gespeichert und wiederverwendet werden.

Übergib `stateCacheFile` an `tw::compile()` (oder `new TailwindCompiler($css, $options)`):

```php
use TailwindPHP\tw;

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

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

Beim ersten Erstellen wird der Status als einfache PHP-Datei unter diesem Pfad gespeichert, die OPcache anfragenübergreifend gemeinsam nutzen kann. Bei späteren Erstellungen wird sie geladen, statt erneut geparst zu werden. Die Ausgabe ist bytegenau identisch mit der eines Compilers ohne Cache.

- Die Datei wird anhand eines Engine-Fingerabdrucks (Größe und Änderungszeit der Quellen und Ressourcen von TailwindPHP), eines Schlüssels aus der Eingabe-CSS sowie den Optionen `base` und `importSearchPaths` und der Größe und Änderungszeit jeder von der Eingabe importierten Datei validiert. Bei einer Abweichung wird sie neu erstellt und geschrieben. Ein Upgrade von TailwindPHP oder eine Änderung an einer importierten Datei erfordert daher keine manuellen Schritte.
- Du verwaltest den Pfad: Verwende eine Datei pro unterschiedlicher Eingabe-CSS in einem Verzeichnis, in das der Webserver schreiben kann. Schreibvorgänge sind atomar (temporäre Datei plus `rename()`).
- Eingaben mit einem benutzerdefinierten `importResolver` umgehen den Cache, da sich das Verhalten des Resolvers nicht per Fingerabdruck erfassen lässt.
- Derselbe Cache ist auch für das Array `compile()` der niedrigeren Ebene verfügbar, API als `TailwindPHP\StateCache\compileCssCached($css, $cacheFile, $options)`.

`tw::generate()` akzeptiert kein `stateCacheFile`; bei jedem Aufruf wird ein neuer Compiler erstellt. Wenn die Erstellungskosten eine Rolle spielen, verwende eine Compiler-Instanz.

## Minimierung

Die Minifizierung verkleinert die Ausgabe für den Produktionseinsatz. Das Flag `minify` gibt direkt während der Serialisierung minifiziertes CSS aus und ist damit der schnellste und präziseste Weg. `tw::minify()` führt den stringbasierten Minifizierer (`src/_tailwindphp/CssMinifier.php`) auf einem vorhandenen CSS-String aus:

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

Beide Wege erzeugen eine gleichwertige Struktur, aber keine identischen Bytes. Der Serializer erhält untergeordnete `:not()`-Selektoren, die der String-Durchlauf zusammenfasst. Verwende daher für generierte Ausgaben bevorzugt das Flag `minify` und `tw::minify()` für CSS, das als String vorliegt.

### Wirkung

Beide Wege nehmen dieselben Größenreduzierungen vor:

| Schritt | Wirkung |
|------|--------|
| Kommentare entfernen | Entfernt `/* … */`-Blöcke |
| Leerraum zusammenfassen | Fasst Folgen von Leerzeichen zusammen und entfernt sie um `{ } ; : ,` und Selektor-Kombinatoren herum |
| Hex-Farben verkürzen | `#ffffff` → `#fff`, `#aabbcc` → `#abc` |
| Einheiten bei Null entfernen | `0px` → `0` (Zeitwerte `0s`/`0ms` bleiben erhalten) |
| Schriftstärke verkürzen | `font-weight:normal` → `400`, `font-weight:bold` → `700` |
| Leere Regeln entfernen | Entfernt Selektoren mit leeren Deklarationsblöcken |

Absichtlich werden weder doppelte Selektoren zusammengeführt noch Kurzschrifteigenschaften kombiniert – beides erschwert die Fehlersuche und kann die Kaskade beeinflussen.

### CLI: `--minify` vs. `--optimize`

Die [CLI](https://tailwindphp.inline0.dev/de/docs/cli) stellt den Minifizierungspfad des Serializers über zwei Flags bereit:

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

In der aktuellen Version minifiziert `--optimize` ebenfalls, sodass beide Befehle dieselben Bytes schreiben ([#9](https://github.com/inline0/tailwindphp/issues/9)). Die lightningcss-äquivalenten Transformationen laufen bei jedem Build. Auch eine einfache Ausgabe (ohne Flag) ist daher bereits optimiert und gut lesbar.

Weitere Informationen zur öffentlichen API – `tw::generate()`, `tw::compile()`, Inspektionsmethoden und Eingabeformaten – findest du in der [API-Referenz](https://tailwindphp.inline0.dev/de/docs/api).
