Производительность и тестирование
TailwindPHP в первую очередь оптимизируется ради корректности. Если изменение для PHP ускоряет работу и не меняет результат, его применяют и помечают как @port-deviation:performance. Соответствие TailwindCSS не предполагается — оно постоянно проверяется набором тестов Tailwind.
Производительность
Порт PHP ставит соответствие результатам TailwindCSS выше максимальной пропускной способности, а исходный TypeScript в любом случае быстрее: JIT-компилятор V8 компилирует часто выполняемые участки в машинный код так, как PHP не может. Для CSS, генерируемого при каждом запросе или для каждой страницы, используйте один компилятор повторно (см. generateExact()) и сохраняйте его состояние после создания с помощью stateCacheFile.
Некоторые часто выполняемые участки кода оптимизированы вручную так, чтобы сохранять идентичный результат:
ast.phptoCss()— накапливает фрагменты в массиве и один раз вызываетimplode, вместо многократной конкатенации строк, а также использует заранее вычисленные строки отступов.css-parser.php— сравнивает символы напрямую, не обращаясь кord(), и отслеживает длину буферов вместо повторного вычисленияstrlen().
Обе оптимизации задокументированы с помощью @port-deviation:performance и проверяются набором тестов — они не могут изменить сгенерированный CSS.
Сравнительные тесты
В директории benchmarks/ находится средство для сравнительных тестов. Запустите его командой:
composer bench # PHP vs TypeScript
composer bench:save # write benchmarks/results.json
Примеры результатов на PHP 8.4.5 / Node.js v22.17.0 (Apple M1):
| Тест | PHP | TypeScript |
|---|---|---|
css-parser в preflight.css |
~816 ops/s | ~15.45K ops/s (≈в 20 раз быстрее) |
toCss |
~65.85K ops/s | ~2.59M ops/s (≈в 39 раз быстрее) |
TypeScript быстрее в этих низкоуровневых операциях, как и ожидалось. Для генерации CSS целых страниц — реального сценария использования — производительности PHP достаточно (примерно 14 мс на страницу в тестовом запуске). При повторении одинакового ввода файловый кэш полностью устраняет эти затраты.
Тестирование и соответствие
Тесты гарантируют, что порт PHP выдаёт тот же результат, что и TailwindCSS. Для этого вместе используются два подхода.
1. Тесты на основе извлечения. Скрипты в test-coverage/ анализируют собственные файлы .test.ts проекта TailwindCSS и извлекают тестовые случаи в JSON. Затем PHPUnit прогоняет их через TailwindPHP и сравнивает результат с ожидаемым CSS. Поскольку эталонные результаты берутся непосредственно из исходного проекта, любое расхождение в поведении PHP обнаруживается как ошибка. Эти тесты охватывают сложные области: утилиты, варианты, интеграцию, функции CSS и тесты уровня браузера ui.spec.
2. Перенесённые вручную модульные тесты. Более простые тестовые файлы TypeScript (AST, разбор CSS, экранирование, разбор кандидатов и значений, …) напрямую перенесены в PHP и размещены рядом с исходным кодом как *.test.php, повторяя структуру и проверки оригиналов.
Цикл состоит из этапов извлечь → запустить → проверить: повторно извлечь тесты из текущего эталона TailwindCSS, запустить набор тестов, и любое расхождение приведёт к ошибке. Так порт остаётся синхронизированным с исходным проектом, а обновление TailwindCSS можно проверять автоматически, а не вручную. При расхождении сборка CI завершается с ошибкой.
composer extract # re-extract test cases from the TailwindCSS reference
composer test # run the full suite
По состоянию на выпуск 1.7.0 (эталон TailwindCSS v4.3.3) пройдено 4,427 тестов:
| Набор | Тесты | Источник |
|---|---|---|
Извлечённые наборы TailwindCSS (утилиты 706, варианты 164, index 148, css-functions 64, ui.spec 68) |
1,150 | извлечены из .test.ts / .spec.ts |
Покрытие API (утилиты, модификаторы, варианты, директивы, плагины, импорты, @source, кэширование, публичный API) |
2,252 | tests/ |
| Модульные тесты рядом с исходным кодом (парсер, AST, кандидаты, тема, утилиты, парсер селекторов, преобразования lightningcss, минификатор) | 767 | порты *.test.php и тесты для PHP |
| CLI (разбор аргументов, вывод, сборки) | 84 | tests/Cli*Test.php |
| Порты плагинов (типографика, формы) | 45 | *.test.php рядом с плагинами |
| Вспомогательные библиотеки (clsx, tailwind-merge, CVA) | 129 | эталонные наборы |
Качество кода
Форматирование и статический анализ выполняются скриптами Composer:
composer lint # Pint --test (check formatting)
composer format # Pint (fix formatting)
composer analyse # PHPStan (static analysis, level 4)
composer quality # lint + analyse
PHPStan выполняет проверку на уровне 4 (phpstan.neon); для динамических форм массивов, используемых в архитектуре на основе функций, задан небольшой список игнорируемых шаблонов. Анализируются все исходные файлы, тестовые файлы исключены.
О структуре, проверяемой этими тестами, и регистрации отклонений см. в разделе Архитектура.