跳转到正文

缓存和压缩

流水线末端有三个生产环境相关事项:避免对相同输入重复编译,避免每次请求都承担构建编译器的开销,以及缩小生成的 CSS。这三者都是围绕编译器的 PHP 端辅助功能。

缓存

每次调用 CSS 都会运行完整流水线。对于请求之间内容不变的情况,基于文件的缓存会将结果写入磁盘,并在后续调用时直接提供。

将 cache 传给 tw::generate();true 表示默认目录,也可以传入自定义路径字符串:

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

如果缓存目录不存在,系统会自动创建。

缓存键

缓存键由 内容、CSS 配置和 minify 标志生成,并用作文件名 tailwind_<hash>.css。标记内容、CSS 输入或是否启用压缩的任何变化,都会生成不同的键,因此对应不同的文件。

键中的 CSS 配置包含内联的 css 以及 importPaths 中列出文件的内容。两种输入不包含在内:这些文件通过嵌套的 @import 引入的文件,以及 TailwindPHP 版本。编辑嵌套导入文件或升级软件包后,请清除缓存,否则系统会继续提供旧输出。

生存时间

cacheTtl 的单位是秒,表示有效时长。命中缓存时,系统会将文件修改时间与当前时间比较;如果文件的时间早于 cacheTtl,则视为未命中并重新编译。若未设置 cacheTtl,缓存条目永不过期,需要手动清除。

清除缓存

tw::clearCache()(或 clearCache() 函数)会从缓存目录中删除 tailwind_*.css 文件,并返回已删除文件的数量。

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

编译器状态缓存

只有相同内容再次出现时,输出缓存才有用。如果每次调用时内容都发生变化,开销较大的是构建编译器本身:解析 @import "tailwindcss"、解析打包资源并累积主题。此阶段仅取决于输入 CSS,因此可以存储并重复使用。

将 stateCacheFile 传给 tw::compile()(或 new TailwindCompiler($css, $options)):

PHP
use TailwindPHP\tw;

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

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

首次构建时,状态会以纯 PHP 文件写入该路径,OPcache 可在请求间共享此文件;后续构建会直接加载该文件,不再重新解析。输出与未使用缓存的编译器逐字节一致。

  • 系统会根据引擎指纹(TailwindPHP 源码和资源的大小及修改时间)、由输入 CSS、base 和 importSearchPaths 选项生成的键,以及输入导入的每个文件的大小和修改时间验证文件。如果不匹配,系统会重新构建并写入文件,因此升级 TailwindPHP 或编辑导入文件时无需手动操作。
  • 路径由你负责:针对每种不同的输入 CSS 使用单独文件,并将其放在 Web 服务器可写入的目录中。写入是原子操作(先写入临时文件,再执行 rename())。
  • 使用自定义 importResolver 的输入会绕过缓存,因为无法为解析器的行为生成指纹。
  • 较低层级的 compile() 数组 API 也可使用同一缓存,方式为 TailwindPHP\StateCache\compileCssCached($css, $cacheFile, $options)。

tw::generate() 不接受 stateCacheFile;每次调用都会构建新的编译器。若需控制构建开销,请使用编译器实例。

压缩

压缩可以缩小生产环境中的输出。minify 标志会在序列化期间直接生成压缩后的 CSS,因此速度最快、精度也最高;tw::minify() 会对现有的 CSS 字符串运行基于字符串的压缩器(src/_tailwindphp/CssMinifier.php):

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

两种路径生成的结构等效,但字节并不完全相同。序列化器路径会保留后代 :not() 选择器,而字符串处理流程会将其折叠,因此生成输出时优先使用 minify 标志;如果 CSS 是以字符串形式传入的,则使用 tw::minify()。

功能说明

两种路径都会应用相同的一组缩减操作:

步骤 效果
移除注释 移除 /* … */ 块
合并空白 合并连续空白,并移除 { } ; : , 周围及选择器组合符周围的空白
缩短十六进制颜色 #ffffff → #fff,#aabbcc → #abc
移除零单位 0px → 0(保留 0s/0ms 时间值)
缩短字重 font-weight:normal → 400,font-weight:bold → 700
移除空规则 删除声明块为空的选择器

按照设计,压缩器不会合并重复选择器或组合简写属性,因为这两种操作都会增加调试难度,并可能影响层叠效果。

CLI:--minify 与 --optimize

CLI 通过两个标志开放了序列化器的压缩路径:

命令行
# 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

在当前版本中,--optimize 也会进行压缩,因此两个命令写入的字节相同(#9)。无论采用哪种方式,每次构建都会运行与 lightningcss 等效的转换,因此不带标志的普通输出已经经过优化且易于阅读。

有关其余公开 API(tw::generate()、tw::compile()、检查方法和输入格式),请参阅 API 参考。