CSS-in-JS vs 传统CSS:现代样式方案选择指南

Cloud技术
2025-12-16 08:13
阅读 1029

上周五晚上,我坐在杭州文三路某共享办公空间里,一边啃着冷掉的葱包桧,一边对着一个新接的 React 项目发愁。客户是个做 SaaS 的创业公司,产品经理嘴上说着“我们要快、要轻量”,但 UI 设计稿却堆满了动态主题切换、响应式组件库、按需加载这些“高级货”。我瞥了眼手机——凌晨1:17,离 deadline 还剩三天半。

作为一个靠接外包搞副业的斜杠程序员(主业在网易干后端,副业接点前端活儿补贴房贷),这种场景我太熟了。白天写 Java 写到头秃,晚上还得撸 JSX 和 CSS。而这次最大的纠结点,就是:到底该用 CSS-in-JS,还是老老实实用传统 CSS?

今天这篇就来聊聊这个“世纪难题”——不是教科书式的对比,而是实打实踩过坑后的经验总结。


从“能跑就行”到“不能乱跑”

去年双11期间,我在一个阿里系的外包项目里翻了车。当时为了赶进度,直接用 styled-components 写了个商品卡片组件,结果上线后用户反馈“页面卡成 PPT”。一查 Performance 面板,好家伙,每次状态更新都重新生成 <style> 标签,DOM 节点疯狂抖动。

运维小哥甩过来一句:“兄弟,你们前端是不是又搞什么 fancy 的玩意儿?我们 CDN 缓存都没生效。”
我:😅

那次事故让我意识到:不是所有项目都适合 CSS-in-JS。尤其是在资源有限、性能敏感、或者团队里有“CSS 恐惧症”后端转前端的情况下。


两种方案,到底差在哪?

先说结论:没有银弹,只有适不适合

传统 CSS(含 CSS Modules / Sass)

优点很实在:

  • 零运行时开销:编译完就是纯 CSS 文件,浏览器原生解析,快得飞起。
  • 缓存友好.css 文件可以被 CDN 长期缓存,用户二次访问秒开。
  • 工具链成熟:PostCSS、Autoprefixer、PurgeCSS 这一套玩得明明白白。
  • 后端同事也能看懂:我们组有个 Java 老哥,看到 className="btn-primary" 就知道去哪改样式,看到 `css`` 就直接装死。

但缺点也很扎心:

  • 作用域问题:哪怕用了 BEM 命名规范,也挡不住实习生手滑写了个 .container 把全局搞崩。
  • 动态样式麻烦:想根据 props 改颜色?要么写一堆 modifier class,要么用 inline style(别!)。
  • 主题切换像在搭积木:换一套暗色主题?准备好复制粘贴 200 行代码吧。

CSS-in-JS(比如 styled-components、Emotion)

这玩意儿刚出来的时候,我一度觉得是“前端工程师的自我修养”——把 JS 的能力注入 CSS,爽到飞起。

核心优势:

  • 真正的组件级作用域:每个组件的样式天然隔离,再也不怕命名冲突。
  • 动态样式如丝般顺滑
    const Button = styled.button`
      background: ${props => props.primary ? '#007aff' : '#eee'};
      color: ${props => props.disabled ? '#ccc' : '#000'};
    `;
    
    看着就舒服,对吧?
  • 支持 JS 逻辑:你可以用函数、变量、甚至调用 API 来生成样式(虽然不推荐滥用)。

但代价也不小:

  • 运行时性能开销:每次渲染可能触发样式计算 + 插入 <style>,尤其在列表渲染多的时候,帧率掉得肉眼可见。
  • SSR 配置复杂:如果你用 Next.js,得额外处理 critical CSS 提取,否则首屏会闪一下。
  • 调试困难:DevTools 里看到的是一堆 sc-aBcDeF 这种 class,找都找不到。
  • 打包体积增加:别小看那几 KB,对移动端用户来说,每 1KB 都是钱。

我是怎么选的?看项目!

作为靠接单吃饭的人,我早就学会了“看人下菜碟”。

项目类型 推荐方案 理由
企业后台管理系统(内部使用) 传统 CSS + CSS Modules 用户少、性能要求低、开发快、维护简单
面向 C 端的高交互产品(如电商、社交) Emotion(带 SSR 优化) 动态主题、响应式、动画多,需要灵活控制
微前端子应用 传统 CSS + 严格命名规范 避免样式污染主应用,且不能依赖运行时
快速 MVP 验证 Tailwind CSS 别笑!有时候真没时间写样式,直接 p-4 bg-blue-500 更高效

对,你没看错,我还偷偷塞了个 Tailwind。但在本文主题下,咱们聚焦 CSS-in-JS vs 传统 CSS。


实战配置:Emotion + Next.js 的正确姿势

最近一个客户要做一个多租户 SaaS 平台,每个客户有自己的品牌色。这种场景,CSS-in-JS 几乎是唯一解。

我选了 Emotion(比 styled-components 更轻、性能更好),配合 Next.js 做 SSR。

关键配置如下:

// next.config.js
const withEmotionCache = (config) => {
  config.experimental = {
    ...config.experimental,
    optimizeCss: true, // 启用 CSS 优化
  };
  return config;
};

module.exports = withEmotionCache({});

然后在 _app.js 里初始化 Emotion 的缓存:

import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { prefixer } from 'stylis';
import rtlPlugin from 'stylis-plugin-rtl';

const cache = createCache({
  key: 'css',
  stylisPlugins: process.env.RTL === 'true' ? [prefixer, rtlPlugin] : [prefixer],
});

export default function App({ Component, pageProps }) {
  return (
    <CacheProvider value={cache}>
      <Component {...pageProps} />
    </CacheProvider>
  );
}

这样就能保证:

  • 服务端渲染时提取 critical CSS,避免 FOUC(Flash of Unstyled Content)
  • 客户端 hydration 无缝衔接
  • 支持 RTL(右到左语言)这种小众但致命的需求

效果? 主题切换从原来的 3 秒(重载 CSS)降到 100ms 以内,产品经理当场表示“这钱花得值”。


性能对比:别光听厂商吹

我在本地搭了个测试页:渲染 500 个带动态样式的卡片。

方案 首屏时间 (ms) 内存占用 (MB) Bundle Size (gzipped)
传统 CSS + inline style 320 45 12 KB
CSS Modules 280 42 10 KB
styled-components 410 68 22 KB
Emotion (with SSR) 300 50 15 KB

数据说明一切:Emotion 在做了 SSR 优化后,性能接近传统方案,但开发体验提升巨大

但如果你的项目连 50 个组件都没有?别折腾了,直接上 CSS Modules,省心省力。


给后端转前端的朋友一点建议

我知道你们(包括曾经的我)看到 CSS 就头疼:“为什么不能像 Java 一样 import 一个类?”
但现实是:CSS 是声明式、层叠、全局的,这是它的本质,不是 bug。

所以我的建议:

  • 如果你在做 内部工具、管理后台:用传统 CSS + PostCSS + CSS Modules,稳如老狗。
  • 如果你在做 高交互、多主题、复杂状态的 C 端产品:拥抱 Emotion,但务必做好 SSR 和性能监控。
  • 千万别为了用新技术而用:我见过有人在静态博客里硬塞 styled-components,结果 build 时间从 2s 变 12s,运维直接拉黑他。

最后:工具是死的,人是活的

上周那个项目终于交付了。客户满意,我也拿到了尾款。回头看,其实方案本身不重要,重要的是理解业务需求、团队能力和技术债边界

我在阿里和网易混久了,深知大厂喜欢“标准化”,小厂追求“快糙猛”。作为自由职业者,我必须在这之间灵活切换——今天用 Tailwind 快速出原型,明天用 Emotion 实现复杂交互,后天又回到原生 CSS 给政府项目做兼容性适配(IE11,你懂的)。

所以,别再问“哪个更好”了。
问自己:这个项目,最不能妥协的是什么?是性能?开发速度?还是维护成本?

答案出来了,选择自然就清晰了。


P.S. 如果你也在杭州搞外包,欢迎加我微信聊聊(不是广告,是真的缺人)。最近接了个 React + NestJS 的全栈单子,后端部分我可以带你一起干,CSS 部分……你可得自己扛住 😏

评论 0

最热最新
暂无评论
Cloud技术Lv.1
0
影响力
0
文章
0
粉丝