| 主要职责 |
编译 Tailwind Web CSS |
生成 Tailwind CSS,并适配小程序模板、JS、CSS、产物和框架生命周期 |
小程序能力必须保留;Generic Web 应裁剪 |
| 支持目标 |
标准 Web/SSR Vite 环境 |
Web、小程序及 uni-app、uni-app x、Taro、weapp-vite 等框架分支 |
产品边界不同 |
| Tailwind 版本 |
与包版本严格同步的 Tailwind 4 |
v5 新生成管线只支持 Tailwind 4,并通过 runtime/generator 封装 |
当前主版本一致 |
| 用户 API |
只有 optimize?: boolean | { minify? } |
appType、generator、cssEntries、tailwindcssBasedir、CSS/JS/template、分包、style injector、生命周期等跨 bundler 配置 |
高级能力合理;Web 默认值需要收敛 |
| 返回的 Vite 插件 |
固定 3 个:scan、generate:serve、generate:build |
Generic Web 当前返回 9 个插件;其他 framework 还会增加 extra plugins |
Web 分支可按 capability 构造 |
| framework 选择 |
不做框架猜测 |
factory 阶段根据 cwd/basedir/env 提前选择 generic/Taro/uni/weapp-vite 分支 |
当前会在 Vite root 可用前冻结,见 #1106 |
| target 选择 |
天然是 Web |
根据 framework/env/显式 generator target 推断;Generic Vite 无平台 env 时回退小程序 |
Generic browser 默认应为 Web,见 #1106 |
| Vite root |
configResolved 后使用真实 root |
factory 先使用 basedir/cwd,configResolved 再对齐 root |
framework plugin 数组无法在对齐后重选 |
| CSS root |
从进入 transform 的 CSS 和 Tailwind directive 建立 compiler |
支持显式 cssEntries、自动 CSS source、placeholder、真实 import、分包入口 |
多入口能力合理;唯一 Vite root CSS 应自动发现 |
| 扫描模型 |
每个 environment + CSS id 持有 compiler/scanner,Oxide 扫描 compiler root/sources |
source collector 扫源码和 transform module,generator 内部还使用 Tailwind scanner |
Generic Web 存在重复扫描,见 #1105 |
| candidate 用途 |
只用于生成 CSS |
还用于验证并精确转译 JS/template class,维护分包 scope 和 runtime class set |
小程序不能直接删除 candidate 层 |
| CSS 生成阶段 |
build/serve 都在 CSS transform 中完成 |
Web 可在 CSS transform 生成;复杂框架还会延后、回放或在 bundle 阶段补全 |
Web 应稳定走 transform 主路径 |
| hook filter |
CSS transform 使用 Vite/Rolldown 原生 transform.filter |
5.3.4 的 Generic Web transform 在 handler 内判断;非 CSS 模块仍跨入 JS hook |
可直接优化,见 #1105 |
| hook 面 |
3 个插件,核心为 configResolved/configureServer/transform/hotUpdate |
9 个 Generic Web 插件覆盖 config/resolveId/load/buildStart/transform/watchChange/handleHotUpdate/generateBundle/closeBundle |
多数为适配能力,不应全部进入纯 Web 热路径 |
| source/output relation |
依赖 Vite module graph 和 scanner files |
为每个子插件包装相同的 watchChange/handleHotUpdate 以维护 source-output relation |
当前一次变更会重复进入多组包装 hook,可集中所有权 |
| HMR |
按 environment/id 缓存;非 CSS 扫描源变化时失效并触发 reload |
维护 candidate diff、append/full regeneration、删除 class 保留策略、补充 CSS update 和 framework fallback reload |
Web 语义应对齐;小程序增强保留 |
| 删除 class |
dev scanner candidate set 为增量集合 |
默认 hmr.preserveDeletedCss: true,也支持完整重生成 |
默认语义接近,但实现不同 |
| Vite Environment API |
状态按 this.environment.name 隔离;resolver 区分 client/SSR |
主要持有单个 ResolvedConfig 和共享 runtime/cache,没有 environment 级隔离 |
SSR/multi-environment 需要明确支持契约 |
| resolver |
使用 Vite CSS/JS resolver,按 environment 处理 client/SSR |
generator/source resolver + placeholder alias + CSS import rewrite |
小程序需要增强;Generic Web 可复用 Vite resolver 语义 |
| 官方插件冲突 |
不处理其他 Tailwind owner |
generator mode 会移除 @tailwindcss/vite 和 @tailwindcss/postcss,并 alias Tailwind import,保证单一生成所有者 |
正确的安全边界,应保留 |
| CSS 兼容处理 |
Tailwind 编译后按 optimize 使用官方 optimize/minify |
还会执行小程序 selector、单位、preflight、变量、cascade layer、平台 CSS 和 Web compat 处理 |
小程序必要;Web 只保留明确的 Web compat |
| JS/template 转译 |
不处理 |
通过已验证 classNameSet 转义 JS、WXML/模板及运行时包名 |
小程序核心能力;Web 应完全跳过加载和注册 |
| bundle 输出 |
不直接接管最终 bundle asset |
可处理 CSS/JS/HTML asset、主样式注入、分包、root import shell、finalizer 和 style injector |
小程序核心能力;Generic Web 已有 fast path,可继续前移门控 |
| CSS code splitting |
交给 Vite |
维护 source-output relation、entry scope、共享/主 CSS 归属 |
多入口/分包需要;普通 Web 应交回 Vite |
| sourcemap |
css.devSourcemap 时返回 Tailwind compiler source map |
多个 transform 返回 map: null,另有 bundle/source relation 与 sourcemap asset 处理 |
不能直接判定最终错误,但需要真实 build/dev parity 门禁 |
| optimize/minify |
optimize 默认开启;是否 minify 跟随 build.cssMinify,可独立关闭 |
没有等价的顶层 Vite option,生成后还经过 style handler 和 Vite CSS pipeline |
应明确 Web option 映射和输出阶段 |
| cache |
按 environment + CSS id 缓存 compiler/scanner/build dependencies |
compiler session、runtime class set、source collector、CSS memory、processed registry、LRU 和 bundle cache |
小程序状态更复杂;Web 应减少重复状态 |
| 日志 |
默认只在 Tailwind DEBUG instrumentation 下输出 |
默认 info,普通 Vite Web 为保持安静需 logLevel: 'silent' |
应跟随 Vite logger,见 #1106 |
| package contract |
声明 Vite ^5.2 || ^6 || ^7 || ^8 peer |
./vite 有导出,但 package 未声明 Vite peer;Node 要求 ^22.18.0 || >=24.11.0 |
建议声明 optional Vite peer 和实际支持矩阵 |
| 依赖与冷启动 |
主要加载 Tailwind node/oxide 和 Vite adapter |
入口静态加载 Babel/OXC、PostCSS adaptor、template、CSS、HMR、bundle 等完整依赖图 |
Generic Web import 慢约 195ms,见 #1105 |
背景与结论
weapp-tailwindcss/vite与@tailwindcss/vite目前不是同一层级的插件:@tailwindcss/vite是面向标准 Vite Web CSS module graph 的 Tailwind 编译器适配层。weapp-tailwindcss/vite同时拥有 Tailwind 生成、小程序候选收集、class 转义、模板/JS/CSS 转译、框架差异、分包样式归属、产物收尾和跨框架 HMR。因此,小程序路径不应该机械追求与官方插件相同的 hook 数量;但 Generic Vite Web 的目标输出就是标准 Web CSS,不需要支付全部小程序 adaptor 成本。建议用本 issue 记录完整差异、明确哪些能力必须保留,并为 Generic Web 建立可量化的收敛边界。
相关执行项:
vite/web专用入口。对照环境
复现项目可使用
weapp-vite/packages/dashboard。它是包含 Vue SFC、Iconify、Monaco 和 ECharts 的 Generic Vite Web SPA。完整差异矩阵
@tailwindcss/viteweapp-tailwindcss/viteoptimize?: boolean | { minify? }appType、generator、cssEntries、tailwindcssBasedir、CSS/JS/template、分包、style injector、生命周期等跨 bundler 配置configResolved后使用真实 rootconfigResolved再对齐 rootcssEntries、自动 CSS source、placeholder、真实 import、分包入口transform中完成transform.filterconfigResolved/configureServer/transform/hotUpdateconfig/resolveId/load/buildStart/transform/watchChange/handleHotUpdate/generateBundle/closeBundlewatchChange/handleHotUpdate以维护 source-output relationhmr.preserveDeletedCss: true,也支持完整重生成this.environment.name隔离;resolver 区分 client/SSRResolvedConfig和共享 runtime/cache,没有 environment 级隔离@tailwindcss/vite和@tailwindcss/postcss,并 alias Tailwind import,保证单一生成所有者optimize使用官方 optimize/minifycss.devSourcemap时返回 Tailwind compiler source mapmap: null,另有 bundle/source relation 与 sourcemap asset 处理optimize默认开启;是否 minify 跟随build.cssMinify,可独立关闭info,普通 Vite Web 为保持安静需logLevel: 'silent'^5.2 || ^6 || ^7 || ^8peer./vite有导出,但 package 未声明 Vite peer;Node 要求^22.18.0 || >=24.11.0当前 Generic Web 插件/hook 实测
@tailwindcss/viteweapp-tailwindcss/vite这里不是要求将 9 个插件强行压缩成 3 个,而是希望 Generic Web profile 不注册确定不会工作的 JS/template/小程序产物 hook,并避免多个插件重复观察同一个 source change。
已确认的正确性与性能边界
test/v5/web-target-official-parity.test.ts,验证 core/Gulp/Webpack Web generator 与官方 Tailwind 输出,以及静态 utility、动态 Iconify plugin 和 filesystem@source。source-candidates后约 1533ms。建议的收敛架构
P0:定义 runtime capability profile
在真实 Vite config/root/environment 可用后,一次性解析以下能力,而不是由各插件重复判断:
由 profile 构造实际插件数组。Generic Web production 默认只保留 CSS root discovery、Tailwind generation 和必要的 Web CSS finalize;显式高级能力再打开对应插件。
P0:为 Generic Web 建立单一扫描所有者
二选一并通过 profile 验证:
不要继续维护两套独立 scanner 再在末端比较结果。候选来源、依赖文件和 HMR invalidation 应有单一所有者。
P1:提供官方插件形状的 Web 入口
建议该入口支持官方的
optimizeoption,并固定 Generic + Web profile。实现上可以复用官方插件、共享 Tailwind compiler adapter,或提供语义等价的轻量实现;关键是不要静态加载 JS/template/mini-program finalizer 依赖。主
WeappTailwindcss()在可靠推断为 Generic Web 后,也应收敛到同一内部 profile,避免维护两套 Web 实现。P1:采用 Vite 原生能力
transform.filter。this.environment.name隔离 compiler/scanner/cache,明确 client、SSR 和未来 environment 行为。watchChange/handleHotUpdate观察集中到一个 owner plugin,避免对子插件重复包装。P1:明确 Web 输出契约
@source和 dependency watch 与官方一致。optimize=false时比较结构化 CSS;开启 optimize/minify 后分别验证语义和字节稳定性。css.devSourcemap、build.sourcemap、CSS code splitting、SSR 与 library mode 的支持范围。P2:补齐 package contract
./vite声明 optional Vite peerDependency,并给出实际支持范围。兼容边界
cssEntries、分包 scope、main CSS matcher、style injector 或 framework extra plugins。appType、generator.target、platform、framework env 和高级配置始终优先于自动 profile。建议回归矩阵
@plugin、@source、source(none)、自定义 variant、任意值和 Iconify 动态 utility。optimizeon/off、cssMinifyon/off、dev/build sourcemap。比较规则建议使用结构化 CSS AST/selector/declaration 集合,避免把压缩变量名、规则顺序或完整 minified snapshot 当作唯一断言。
完成标准