UnoCSS CLI 完全指南:用 @unocss/cli 在传统后端与命令行工作流中生成原子化 CSS
【免费下载链接】unocssThe instant on-demand atomic CSS engine.项目地址: https://gitcode.com/GitHub_Trending/un/unocss
@unocss/cli是 UnoCSS 的命令行入口,专为无法(或不便于)接入构建工具插件体系的"传统后端"场景设计:只需给定一组 glob 扫描模式,它就能从模板、脚本文件中提取类名、应用 transformers、并产出可直接部署的uno.css。本文以packages-engine/cli/README.md及其指向的官方文档 CLI 集成文档 为核心,结合 CLI 源码实现 与 测试用例,完整覆盖安装、全部命令行选项、配置文件中的cli.entry高级用法、--rewrite与--split-css的底层行为,以及 watch 模式的工作机制。
包定位与安装
@unocss/cli的包描述为 "CLI for UnoCSS",当前仓库中版本号为66.10.0(见 package.json),通过bin字段暴露unocss可执行命令(bin/unocss.mjs)。它独立于 Vite、PostCSS、Webpack 等集成方式,核心价值在于:
- 从任意 glob 匹配的文件中扫描并提取 utilities;
- 内置
--watch开发监听模式; - 通过
uno.config.ts支持完整自定义配置; - 提供多个输出选项(输出文件名、stdout、压缩、重写源文件、CSS 拆分等);
- 支持多个 entry pattern,分别产出不同 CSS 文件。
安装有两种方式。CLI 随unocss全量包一起分发:
pnpm add -D unocss # 或 yarn / npm / bun yarn add -D unocss npm install -D unocss bun add -D unocss也可以只安装独立的 CLI 包:
pnpm add -D @unocss/cli yarn add -D @unocss/cli npm install -D @unocss/cli bun add -D @unocss/cli注意:官方文档特别提示,如果你找不到
unocss二进制(例如使用pnpm且只安装了unocss包),需要显式安装@unocss/cli独立包。
基本用法:glob 模式与多入口
CLI 接受一个或多个 glob 模式作为位置参数:
unocss "site/snippets/**/*.php" "site/templates/**/*.php"配合 npm scripts 的典型配置(注意官方文档强调:npm script 中的 glob 模式要加转义引号,防止 shell 提前展开):
{ "scripts": { "dev": "unocss \"site/{snippets,templates}/**/*.php\" --watch", "build": "unocss \"site/{snippets,templates}/**/*.php\"" }, "devDependencies": { "@unocss/cli": "latest" } }开发时用--watch(或-w)监听文件变化,生产构建直接运行不带--watch的命令即可。默认情况下,最终产物uno.css会生成在当前工作目录。
如果既没有提供 glob 模式,也没有在配置文件中定义cli.entry,CLI 会抛出一个友好的PrettyError,提示形如No glob patterns provided. Try unocss <path/to/**/*> or configure entries in uno.config file,并将进程退出码置为 1(见 resolveOptions 中的校验逻辑 与 errors.ts)。
选项解析细节
所有命令行选项在 cli-start.ts 中基于cac注册,默认值与文档表格一致:
--out-file默认解析为<cwd>/uno.css;--preflights默认true(默认开启 preflight 样式);--split-css默认true;--preset默认wind4;--stdout模式下,--watch与--out-file会被忽略,且日志会重定向到 stderr,保证 stdout 只有纯 CSS 输出(有专门的测试keeps cli logs off stdout验证这一点,见 cli.test.ts)。
配置文件:uno.config.ts与cli.entry
在项目根目录创建uno.config.js或uno.config.ts即可自定义 UnoCSS。除了 presets、theme、rules 等通用配置外(详见 UnoCSS 配置文档),CLI 提供了专属的cli配置块,用于"不同级别的文件打包与重写":
import { defineConfig } from 'unocss' export default defineConfig({ cli: { entry: {}, // CliEntryItem | CliEntryItem[] }, // ... }) interface CliEntryItem { /** * Glob patterns to match files */ patterns: string[] /** * The output filename for the generated UnoCSS file */ outFile: string /** * Whether to rewrite the transformed utilities. * * - For css: if rewrite is true, it will not generate a new file, but directly modify the original file content. * - For other files: if rewrite is true, it replaces the original file with the transformed content. * * @default false */ rewrite?: boolean /** * Whether to output CSS files scanned from patterns to outFile * * - false: Do not output CSS files * - true: Transform and output scanned CSS file contents to outFile * - 'multi': Output each CSS file separately with filename format `${originFile}-[hash]` * - 'single': Merge multiple CSS files into one output file named `outFile-merged.css` * * @default true */ splitCss?: boolean | 'multi' | 'single' }从 resolveOptions 源码 可以看到入口的合并规则:
- 命令行传入的
patterns会被包装成第一个 entry,outFile取--out-file值(默认<cwd>/uno.css); uno.config中cli.entry(单个对象或数组,经toArray归一化)逐项追加,每一项的rewrite/splitCss若未显式设置,则回落到命令行--rewrite/--split-css的值;- 两套 entry 共同构成
options.entries,构建时并行生成各自的输出文件。
测试用例supports unocss.config.js cli options验证了多入口场景:配置中声明views/index1.html → ./uno1.css、views/index2.html → ./test/uno2.css两条 entry,构建后两个输出文件分别包含各自的.bg-blue与.bg-red规则(见 cli.test.ts)。
Rewrite 源文件:--rewrite
--rewrite会让 CLI 把经过 transformers 变换后的内容写回源文件本身,适合希望把 Variant Groups、Compile Class 等变换直接固化进代码的场景:
unocss "src/**/*.vue" --rewrite旧的--write-transformed选项已废弃,源码中遇到它时仍会兼容处理,但打印警告--write-transformed is deprecated, please use --rewrite instead(见 resolveOptions 中的警告逻辑)。
transformers 的执行顺序在 transformFiles 中固定为pre → default → post三个阶段依次调用applyTransformers。测试applies pre, default, and post transformers精确验证了这一顺序:三个自定义 transformer 分别向<div></div>前置<div class="bg-red">、追加<div class="bg-blue">与<div class="p-4">,最终文件内容为三段拼接的确定顺序,且生成 CSS 中同时包含.bg-red、.bg-blue、.p-4。
以 Variant Group 为例(官方文档推荐搭配 transformers/variant-group 或 transformers/compile-class):
# 配置中启用 transformerVariantGroup() 后 unocss "views/index.html" --rewrite # <div class="border-(~ solid red)"></div> → 被展开为 border-solid border-red 等标准类对应测试见 supports variantGroup transformer。
CSS 拆分:--split-css
当扫描模式中混入了.css文件时,--split-css控制这些 CSS 如何进入产物:
unocss "src/**/*.vue" --split-css true|false|multi|single| 取值 | 行为 |
|---|---|
false | 不输出 CSS 文件(直接丢弃扫描到的.css) |
true | 转换后的 CSS 内容并入outFile |
multi | 每个 CSS 文件单独输出,文件名为${originFile}-[hash].css |
single | 合并为outFile-merged.css |
parseEntries 源码 清晰展示了这四种分支:
true:CSS 文件内容追加进outFile对应的缓存桶;single:全部 CSS 归入以outFile去掉.css后拼-merged.css命名的桶(outFile.replace(/(\.css)?$/, '-merged.css'));multi:为每个文件计算hash(file),输出${file}-${hash}.css;当该 entry 只匹配到一个文件时,退化为直接写入outFile(files.length > 1 ? currentOutFile : outFile);false:CSS 文件被静默丢弃。
并入outFile的 CSS 在产物中带有/* Source: <file> */来源注释,便于溯源(CI 环境下不带注释,见 generateSingle)。
默认 Preset:--preset
当项目中没有找到uno.config时,可以用--preset指定 CLI 使用的默认 preset:
unocss "src/**/*.vue" --preset wind3|wind4wind4:加载@unocss/preset-wind4;wind3:加载@unocss/preset-wind3。
注意:如果配置了
uno.config,该选项会被忽略。
源码层面,initializeConfig 在configSources为空时动态import对应 preset 包,并同时挂入transformer-directives(即默认支持@apply指令),然后ctx.uno.setConfig注入。这与 use default preset via cli option 测试(--preset wind4下bg-blue与@apply均生效)相互印证。
官方文档还有一条版本约束值得记住:自v66.6.0起,@unocss/cli不再"静默"提供默认 preset——要么显式传--preset,要么在配置文件中声明 presets。在wind3与wind4两代 preset 并存期间,这一显式选择可以避免产物差异带来的困惑。
完整命令行选项速查
以下为 CLI 文档选项表 的完整内容,并对照 cli-start.ts 中的注册代码 核实了默认值:
| Options | 说明 | 默认值 |
|---|---|---|
-v, --version | 显示当前 UnoCSS 版本 | — |
-c, --config [file] | 指定配置文件路径 | 自动探测 |
-o, --out-file <file> | 生成的 UnoCSS 文件名 | <cwd>/uno.css |
--stdout | 将生成的 CSS 写入 STDOUT;会忽略--watch与--out-file | false |
-w, --watch | 监听 glob 匹配到的文件变化 | false |
--preflights | 是否输出 preflight 样式 | true |
--rewrite | 用变换后的 utilities 回写源文件 | false |
--write-transformed | 同--rewrite(已废弃) | false |
-m, --minify | 压缩生成的 CSS | false |
--debug | 启用调试模式(打印文件生成明细表) | false |
--split-css [mode] | 控制扫描到的 CSS 文件的输出方式:true/false/multi/single | true |
--preset [default-preset] | 在无配置文件时切换wind3/wind4默认 preset | wind4 |
-h, --help | 显示可用 CLI 选项 | — |
补充两个源码中可见但文档未逐字展开的行为:
--stdout与--out-file互斥校验:显式同时指定时直接logger.fatal报错退出;--debug会调用 debugDetailsTable,以表格形式打印每个输出文件与其来源文件的对应关系(File Generation Details:),排查多 entry 映射问题时非常有用。
内部构建流程与 Watch 模式
build 函数 串起完整管线:initializeConfig→resolveOptions→parseEntries(tinyglobby 扫描)→ 非 watch 模式直接generate,watch 模式则先startWatcher再按需重建。
Watch 模式要点(实现见 watcher.ts):
- 底层使用
chokidar,usePolling: true、interval: 100(轮询而非 inotify,兼容性优先),并忽略**/{.git,node_modules}/**; - 监听范围包括所有已匹配的源文件以及配置文件本身(
ctx.getConfigFileList()); - 触发事件后统一经 100ms 的
perfect-debounce防抖再重新generate; - 源文件
change时只更新缓存中的代码内容,unlink时从缓存移除,add时重新parseEntries; - 配置文件变化会触发
ctx.reloadConfig(),重新解析 options 与 entries 后再重建——测试supports uno.config.ts changed rebuild验证了修改uno.config.ts主题色后产物即时从red变为blue(见 cli.test.ts)。
产物生成阶段(generateSingle)的关键步骤:
- 对每个源文件依次执行 pre/default/post transformers;
- 去除
@unocss-skip-start/@unocss-skip-end之间的内容(SKIP_COMMENT_RE),这是官方测试@unocss-skip uno.css覆盖的特性:skip 块中的bg-red、text-white不会出现在产物里; - 非 CSS 文件调用
ctx.uno.generate(input, { preflights: false, minify: true, id })只收集matched token 集合,不产出 CSS; - 若
rewrite开启,将transformedCode写回原文件; - 用 token 集合做最终一次
generate(此时才应用preflights与minify选项),拼接扫描到的 CSS 内容后写入outFile(目录不存在会自动mkdir -p)。
两阶段 generate 的设计意味着:preflight 与最终压缩只执行一次,与源文件数量无关。
测试覆盖一览
cli.test.ts 为上述行为提供了完整回归保障,主要用例包括:
- 基本构建:
<div class="p-4 max-w-screen-md">→ 快照断言uno.css; - CSS 扫描 + 变换:
@apply指令经transformer-directives展开; --preset wind4默认 preset 行为;unocss.config.js(shortcuts)与cli.entry多输出文件;--rewrite下 Variant Group、directives 的源文件回写;- pre/default/post transformer 顺序与错误传播(transformer 抛错会中断构建);
- 含
@media的混合类型文件去重正确性; @unocss-skip注释块排除;--stdout模式下 stdout 纯净性;- watch 模式下源文件变更与配置文件变更的重建(Node 20 下跳过 watch 用例)。
小结
@unocss/cli把 UnoCSS 的核心能力压缩成一条命令:glob 模式定义"扫什么",uno.config.ts的cli.entry定义"输出到哪",--rewrite让 transformers 直接改写源码,--split-css精确控制伴随 CSS 的去向,--preset决定无配置时的默认风味。对于 PHP、Laravel、Django 等传统后端模板项目,或者任何不便引入前端构建工具的场景,它提供了与 Vite/PostCSS 集成同等表达力的替代路径,且 watch 模式下的文件级增量缓存与配置热重载使开发体验同样完整。
【免费下载链接】unocssThe instant on-demand atomic CSS engine.项目地址: https://gitcode.com/GitHub_Trending/un/unocss
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考