Vanilla-extract能显著减小JS包体积,因其采用零运行时架构:样式逻辑在构建期通过插件编译为静态CSS,仅导出轻量类名变量,JS包中不包含任何样式计算、插入或更新逻辑,典型项目减少15–30% JS体积。
CSS-in-JS 框架本身不是体积问题的根源,但 styled-components、emotion 等默认打包行为会把运行时 + 样式解析逻辑 + 生成逻辑全打进 JS 包,动辄 15–30KB(gzip 后),且 Tree Shaking 效果差——Vanilla-extract 是少数能真正“编译期提取 CSS”的替代方案。
它不把样式逻辑留在运行时,而是借助 TypeScript 编译插件(@vanilla-extract/esbuild-plugin 或 @vanilla-extract/webpack-plugin)在构建阶段就把样式转成静态 CSS 文件,并导出极轻量的 class 名变量(如 const className = 'src_button__abc123')。JS 包里不再含任何样式计算、插入、更新逻辑。
style 标签、不维护样式注册表Vanilla-extract 不是“换个 import 就行”的平替,它强制样式与组件分离,且依赖构建时编译。常见卡点:
createTheme 和 globalStyle 必须写在 .css.ts 文件中,不能放在 React 组件文件里;否则插件无法扫描到,构建时报 VanillaExtract: No styles found
theme 或 props 切换)需用 recipe + variants 声明,不能写 css({ color: props.primary ? 'blue' : 'gray' }) 这类运行时表达式getStylesheet 或 extractCss 提取关键 CSS,否则首屏无样式;Vite 用户需配合 vite-plugin-vanilla-extract,而非仅靠 cssModules 配置以一个中等规模管理后台为例(含主题切换、暗色模式、按钮/表格/表单组件):
立即学习“前端免费学习笔记(深入)”;
styled-components@6:JS 包含运行时 + 所有组件样式定义,gzip 后 28KBvanilla-extract@2 + @vanilla-extract/css:JS 部分降至 0.9KB,CSS 单独 14KB(可进一步压缩 + 分片)styled.div 的链式写法或 asChild 等高级能力,直接迁移成本高;建议优先从新模块或原子组件(Button、Input)开始试点Vanilla-extract 的硬约束很明确:它只接受“编译期可静态分析”的样式逻辑。一旦你写了 css({ fontSize: `${size}px` }) 或基于用户输入动态生成规则,就得退回到 runtime CSS-in-JS 方案——这时候与其强行适配,不如用 goober(css-render(支持浏览器端动态生成)补位。