性能与测试
TailwindPHP 优先保证正确性。若特定于 PHP 的改动能在不改变输出的前提下提升速度,就会采用并标记为 @port-deviation:performance。不会假定与 TailwindCSS 保持一致,而是持续使用 Tailwind 自带的测试套件进行验证。
性能
PHP 移植版本优先匹配 TailwindCSS 的输出,而非追求原始吞吐量;无论如何,原版 TypeScript 都更快——V8 的 JIT 会将热点路径编译为原生代码,这是 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 ms)。对于重复的相同输入,文件缓存 可以彻底消除开销。
测试与一致性
测试用于确保 PHP 移植版本生成的输出与 TailwindCSS 相同。两种方法相互配合。
1. 基于提取的测试。 test-coverage/ 中的脚本会解析 TailwindCSS 自带的 .test.ts 文件,并将测试用例提取到 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、索引 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 |
| 插件移植版本(typography、forms) | 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),并忽略少量模式,以适应基于函数的架构所使用的动态数组形态。所有源文件都会接受分析;测试文件除外。
关于这些测试验证的结构以及偏差记录位置,请参见 架构。