You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于emotion/css与Next.js App Router集成的疑问

关于emotion/css与Next.js App Router集成的疑问

我完全懂你找了好几天答案的那种焦虑!其实核心原因在于emotion/css和emotion/styled的底层运行逻辑,以及它们适配Next.js App Router SSR模型的方式差异,咱们一步步说:

1. 两者的本质区别:组件式 vs 函数式className生成

  • emotion/styled 是组件封装:它返回的是一个React组件,内部已经帮你处理了样式的注入、SSR时的样式收集,以及客户端 hydration 的匹配逻辑。比如你写styled.div,本质是创建了一个自带样式的div组件,这个组件天然就知道该在客户端还是服务器端怎么处理样式。
  • emotion/css 是函数式生成className:它只是帮你把样式字符串编译成一个唯一的className,然后需要你手动在组件的className属性里应用。这种方式没有封装组件级别的样式处理逻辑,所以在App Router的服务器组件/客户端组件分离模型下,样式收集和注入的逻辑就容易出问题。

2. App Router的SSR规则限制了emotion/css的发挥

Next.js App Router的核心是服务器组件(Server Components)和客户端组件(Client Components)的严格区分:

  • 服务器组件不能执行任何客户端侧的副作用(比如样式注入、DOM操作),但emotion/css的css()函数如果在服务器组件里调用,生成的样式无法被收集到服务器端的全局样式表中,最终会导致客户端 hydration 时样式缺失,出现样式不匹配的问题。
  • 而emotion/styled生成的组件,你必须加上'use client'指令才能使用(因为它需要客户端环境来注入样式),这刚好符合App Router的规则——客户端组件负责处理所有需要客户端交互/副作用的逻辑,包括样式注入。同时Emotion的SSR工具能自动收集这些客户端组件的样式,在服务器端渲染时一并输出。

3. 为什么Material UI能正常工作?

MUI本身就是用emotion/styled封装的组件库,所有MUI组件都默认是客户端组件(已经内置了'use client'的逻辑),并且MUI团队已经针对App Router的SSR做了适配,处理了样式收集、注入和hydration匹配的问题,所以它能直接用。

要不要转emotion/styled?

给你两个方向的建议:

  • 如果不想换写法:可以尝试把所有使用emotion/css的组件都标记为'use client',然后在App Router的根客户端组件(比如layout.tsx里的客户端包裹组件)中配置Emotion的SSR提供者,手动处理样式收集。不过这种方式可能会遇到一些边缘问题(比如服务器组件里完全没法用css()),而且没有官方支持,后续可能会有兼容性风险。
  • 如果想省心:转emotion/styled是更稳妥的选择。现在社区里的workaround都是针对它的,而且Emotion团队的官方App Router支持也是优先覆盖styled方案,后续的维护和更新会更及时,加上有MUI的实践案例,踩坑的概率会小很多。

备注:内容来源于stack exchange,提问作者user3158803

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 06:19:29