CSS-in-JS vs 传统CSS:一个天通苑奶爸的深夜技术抉择
上周五晚上11点27分,我终于把两个娃——三岁半的乐乐和一岁半的米粒——哄睡了。老婆在客厅刷《甄嬛传》重播(她说这剧能解压),我轻手轻脚溜进次卧,打开那台服役四年的MacBook Pro,屏幕幽光照亮了我布满黑眼圈的脸。
那天白天刚被主管拉去开需求评审会,新项目要用React重构老后台系统。散会后他拍拍我肩膀:“老张,样式这块你来定方案吧,别再用那些老旧的BEM命名了。” 我点头应下,心里却咯噔一下——CSS到底该怎么写?用CSS Modules?还是试试最近很火的Styled Components?
坐标北京天通苑,房租3500一个月(合租),月薪18k,房贷车贷加奶粉钱每月雷打不动支出1.6w。作为两个娃的奶爸,我比谁都清楚:一次错误的技术选型,可能让我加班到凌晨三点,而凌晨三点的我,第二天根本扛不住乐乐早上六点的“爸爸起床!”攻击。
从一场失败的面试说起
其实我对“怎么写CSS”这个问题的焦虑,早在去年十月就埋下了种子。
那会儿我在看新机会,面了一家做跨境电商的A轮融资公司。技术二面时,面试官是个戴黑框眼镜、说话慢悠悠的前端TL。聊完React原理和性能优化后,他突然问:
“你们项目现在用什么样式方案?为什么选它?有没有考虑过CSS-in-JS?”
我当时支支吾吾说用了SCSS + BEM,因为“团队熟悉”、“好维护”。他点点头没多问,但后来HR委婉告诉我:“技术深度还可以,但在工程化和现代前端实践上略显保守。”
回家路上,地铁13号线挤得像沙丁鱼罐头,我盯着手机里那封拒信,心里不是滋味。月薪从15k涨到22k的机会,可能就卡在了这个“样式方案”的问题上。
当晚哄睡孩子后,我翻出掘金、知乎、GitHub Trending,一口气看了十几篇关于CSS-in-JS的文章。越看越懵:Emotion、Styled Components、Linaria、Vanilla Extract……这些工具名字听着就高级,但真的适合我们这种中小团队吗?
更关键的是——它们会不会让我本就不多的睡眠时间再少一小时?
真实项目中的血泪教训
今年3月,我们接了个政府数据可视化项目,工期紧、UI复杂。我一咬牙,决定试水Styled Components。
第一天还挺兴奋:“看!动态主题切换一行代码搞定!”
第三天就开始骂娘:“为什么热更新这么慢?改个颜色要等8秒?!”
第七天彻底崩溃:一个简单的hover效果,因为props嵌套太深,生成了一串长得离谱的类名,DevTools里根本没法调试。
最要命的是,项目中期来了个新人小李——985科班,但只用过传统CSS。他对着满屏的styled.div一脸懵:“张哥,这个按钮的样式在哪改?全局变量又在哪?”
我花了整整一个下午给他讲ThemeProvider、css prop、Server-Side Rendering注意事项……那一刻我突然意识到:技术选型不只是“哪个更先进”,而是“团队能不能高效协作”。
后来我们紧急回滚到CSS Modules + PostCSS,虽然少了些酷炫功能,但至少小李第二天就能独立开发页面了。上线那天,客户夸界面清爽,没人知道背后我们为样式方案吵过三次会。
奶爸的深夜实验室:亲自下场对比
既然实战踩过坑,不如自己动手测一测。于是过去两个月,每个娃睡后的23:30-1:30,成了我的“CSS方案压力测试时间”。
我建了三个几乎一样的React应用(用Vite搭的,别卷Webpack了):
- 传统派:CSS Modules + SCSS + BEM命名
- 中间派:CSS Modules + PostCSS(支持嵌套、变量)
- 激进派:Emotion(社区目前最稳的CSS-in-JS方案)
测试维度 & 结果(真实数据!)
| 维度 | 传统CSS | Emotion (CSS-in-JS) |
|---|---|---|
| 首屏加载 | 23KB CSS文件 | JS包增大42KB(含运行时) |
| 热更新速度 | 平均1.2s | 平均3.8s(开发模式) |
| 主题切换 | 需要CSS变量+JS切换class | 直接传theme props,秒切 |
| 组件隔离性 | 靠命名规范,偶尔污染 | 天然作用域隔离,零冲突 |
| 新人上手成本 | 1天(只要会CSS) | 2-3天(需理解JSX+样式混合逻辑) |
| 服务端渲染 | 静态文件直接引用 | 需额外配置extractCritical |
最关键的发现:在我们的实际业务中(中后台管理系统,80%是表单/表格),传统CSS的开发效率反而更高。因为:
- 设计稿基本固定,很少需要“根据props动态算样式”
- 全局统一的按钮、输入框样式,用CSS变量维护比在每个组件里import theme更直观
- 调试时直接右键“检查元素”就能改样式,不用翻半天JSX找styled定义
但!如果你在做高度动态的营销页、或者需要频繁换肤的C端产品,CSS-in-JS的优势就碾压了。比如我们另一个H5活动页项目,用Emotion配合Framer Motion做交互动效,简直丝滑到飞起。
工具链的隐藏成本:别只看API多优雅
很多教程吹CSS-in-JS时,只展示这行代码有多美:
const Button = styled.button`
background: ${props => props.primary ? 'palevioletred' : 'white'};
color: ${props => props.primary ? 'white' : 'palevioletred'};
`;
但没人告诉你:
- 打包体积增加:Emotion运行时约8KB(gzip后),对性能敏感的项目可能是负担
- Source Map错位:报错时定位不到原始样式代码,调试体验降级
- 缓存失效:JS更新会导致整个样式缓存失效,而传统CSS可单独缓存
- TypeScript支持:虽然现在有
@emotion/react的TS类型,但写起来还是比纯CSS啰嗦
上周四凌晨1点,我就被一个诡异bug折磨了两小时:某个Table组件在SSR时样式错乱,CSR后才恢复正常。最后发现是Emotion的CacheProvider没配好。而同样的问题,在传统CSS里根本不会存在——静态资源就是静态资源。
作为奶爸程序员,我越来越怕“聪明但脆弱”的方案。孩子半夜发烧时,我可没心思研究为什么CSS-in-JS在Node环境渲染异常。
面试题背后的真相:面试官到底想听什么?
回到开头那场失败的面试。现在我明白了,面试官问“CSS方案选择”,根本不是要你背工具优缺点,而是考察你的工程思维:
- 你是否考虑团队规模和成员水平?
- 你是否权衡过长期维护成本?
- 你是否根据业务场景做决策?
所以现在如果再有人问我,我会这样答:
“我们目前主力项目用CSS Modules + PostCSS。原因有三:
- 团队5个前端,2个实习生,降低学习成本;
- 项目90%是管理后台,动态样式需求少;
- 性能指标要求FCP<1.2s,避免JS运行时开销。
但我们在新孵化的H5活动页中试水Emotion,因为需要大量动画和主题定制。技术没有银弹,只有‘当下最合适’的方案。”
你看,重点不是工具本身,而是你的决策逻辑。这比背八股文有用多了。
给 fellow 奶爸程序员的建议
写到这里,窗外天通苑的早班车已经呼啸而过。再过两小时,乐乐又要爬起来喊“爸爸做 pancakes!”。
作为一个在生存线上挣扎的技术人,我想分享几点掏心窝子的话:
别被“新技术焦虑”绑架
CSS-in-JS很酷,但如果你的业务用不到它的核心优势(动态样式、强隔离),何必自找麻烦?稳定交付比技术炫技重要一百倍——尤其是当你需要准时下班接娃放学的时候。把“可维护性”放在第一位
想想六个月后的自己:当需求变更时,你是希望看到清晰的.btn-primary,还是在JSX里翻三层props找颜色值?代码是写给人看的,其次才是机器。小步快跑,别all in
如果真想尝试CSS-in-JS,先在一个非核心页面试点。就像我先拿H5活动页试水,而不是直接重构主系统。和设计师对齐预期
很多团队引入CSS-in-JS是因为设计师总改色值。但其实用CSS变量 + Design Token也能解决。工具服务于流程,别让流程迁就工具。
最后:技术人的尊严不在工具链,而在解决问题
昨天老婆看我熬夜查文档,叹了口气说:“要不咱们回老家吧?你在这累死累活,图啥呢?”
我没回答。但今天写这篇文章时,我突然有了答案:
我图的不是用上最潮的框架,而是在有限的时间里,做出既稳定又高效的系统——这样我才能在周五晚上陪乐乐搭乐高,而不是在工位上改第17版hover效果。
CSS-in-JS or not?这个问题没有标准答案。但作为两个娃的奶爸,我的答案很朴素:
选那个让你少加班、多陪娃的方案。
毕竟,孩子的成长只有一次。而CSS,明天还能接着写。
后记:本文所有测试数据基于个人MacBook Pro 2019 (i5/16GB),React 18 + Vite 4环境。如果你也在天通苑租房、家里有俩神兽、还在纠结技术选型——欢迎留言聊聊。说不定哪天咱能在龙德广场的麦当劳,一边啃汉堡一边吐槽webpack配置呢 :)

评论 0