Zum Inhalt springen

Performance und Tests

TailwindPHP optimiert vorrangig auf Korrektheit. Wenn eine spezifische Änderung für PHP die Leistung steigert, ohne die Ausgabe zu verändern, wird sie übernommen und als @port-deviation:performance gekennzeichnet. Die Parität mit TailwindCSS wird nicht vorausgesetzt, sondern laufend anhand der eigenen Testsuite von Tailwind überprüft.

Leistung

Beim PHP-Port hat die Übereinstimmung mit der TailwindCSS-Ausgabe Vorrang vor dem reinen Durchsatz; das Original TypeScript bleibt ohnehin schneller — V8s JIT kompiliert häufig ausgeführte Pfade zu nativem Code, was PHP nicht erreichen kann. Wenn CSS pro Anfrage oder Seite erzeugt wird, verwende einen Compiler erneut (siehe generateExact()) und speichere seinen Konstruktionszustand mit stateCacheFile.

Einige häufig ausgeführte Pfade enthalten von Hand optimierte Stellen, die identische Ausgaben gewährleisten:

  • ast.php toCss() — sammelt Fragmente in einem Array und führt implode einmal aus, statt wiederholt Zeichenfolgen zu verketten, und verwendet vorab berechnete Einrückungszeichenfolgen.
  • css-parser.php — vergleicht Zeichen direkt, statt ord() zu durchlaufen, und erfasst Pufferlängen, statt strlen() neu zu berechnen.

Beide sind mit @port-deviation:performance dokumentiert und an die Testsuite gebunden — sie können die erzeugte CSS nicht verändern.

Benchmarks

Das Verzeichnis benchmarks/ enthält ein Vergleichsprogramm. Führe es so aus:

Shell
composer bench         # PHP vs TypeScript
composer bench:save    # write benchmarks/results.json

Beispielergebnisse mit PHP 8.4.5 / Node.js v22.17.0 (Apple M1):

Benchmark PHP TypeScript
css-parser auf preflight.css ~816 ops/s ~15.45K ops/s (≈20× schneller)
toCss ~65.85K ops/s ~2.59M ops/s (≈39× schneller)

TypeScript ist bei diesen Low-Level-Operationen erwartungsgemäß schneller. Für die Erzeugung von CSS für ganze Seiten — den eigentlichen Anwendungsfall — ist die Leistung von PHP ausreichend (im Beispiel etwa 14 ms pro Seite). Bei wiederholter identischer Eingabe entfallen die Kosten dank des Datei-Caches vollständig.

Tests und Parität

Die Tests stellen sicher, dass der PHP-Port dieselbe Ausgabe wie TailwindCSS erzeugt. Dafür kommen zwei Ansätze zusammen.

1. Extraktionsbasierte Tests. Skripte in test-coverage/ lesen TailwindCSSs eigene .test.ts-Dateien ein und extrahieren die Testfälle nach JSON. PHPUnit führt diese Fälle über TailwindPHP aus und vergleicht die Ausgabe mit dem erwarteten CSS. Da die erwarteten Ergebnisse direkt aus dem Upstream-Projekt stammen, zeigt jeder Unterschied im Verhalten von PHP einen Fehler an. Abgedeckt sind komplexe Bereiche: Utilities, Varianten, Integration, CSS-Funktionen und Tests auf Browserebene mit ui.spec.

2. Manuell portierte Unit-Tests. Einfachere TypeScript-Testdateien (AST, CSS-Parsing, Escaping, Parsing von Kandidaten und Werten, …) werden direkt nach PHP portiert und liegen als *.test.php neben ihrer jeweiligen Quelldatei. Dabei werden Aufbau und Assertions der Originale übernommen.

Der Ablauf lautet extrahieren → ausführen → prüfen: Extrahiere die Tests erneut aus der aktuellen TailwindCSS-Referenz und führe die Testsuite aus. Jede Abweichung schlägt fehl. So bleibt der Port mit dem Upstream-Projekt synchron, und ein TailwindCSS-Update lässt sich mechanisch statt durch Sichtprüfung validieren. Bei Abweichungen schlägt CI fehl.

Shell
composer extract   # re-extract test cases from the TailwindCSS reference
composer test      # run the full suite

Seit Release 1.7.0 sind 4.427 Tests bestanden (TailwindCSS-Referenz v4.3.3):

Testsuite Tests Quelle
Extrahierte TailwindCSS-Testsuites (Utilities 706, Varianten 164, Index 148, CSS-Funktionen 64, ui.spec 68) 1,150 extrahiert aus .test.ts / .spec.ts
API-Abdeckung (Utilities, Modifikatoren, Varianten, Direktiven, Plugins, Imports, @source, Caching, öffentliche API) 2,252 tests/
Unit-Tests neben dem Quellcode (Parser, AST, Kandidaten, Theme, Hilfsfunktionen, Selektor-Parser, lightningcss-Transformationen, Minifier) 767 *.test.php-Ports und PHP-spezifische Tests
CLI (Argument-Parsing, Ausgabe, Builds) 84 tests/Cli*Test.php
Plugin-Ports (Typography, Forms) 45 *.test.php neben den Plugins
Begleitbibliotheken (clsx, tailwind-merge, CVA) 129 Referenztestsuites

Codequalität

Formatierung und statische Analyse laufen über Composer-Skripte:

Shell
composer lint      # Pint --test  (check formatting)
composer format    # Pint         (fix formatting)
composer analyse   # PHPStan      (static analysis, level 4)
composer quality   # lint + analyse

PHPStan läuft auf Level 4 (phpstan.neon), mit einer kurzen Liste ignorierter Muster für die dynamischen Array-Strukturen der funktionsbasierten Architektur. Alle Quelldateien werden analysiert; Testdateien sind ausgeschlossen.

Die Struktur, die diese Tests prüfen, und die dokumentierten Abweichungen findest du unter Architektur.