emotion 卡顿主因是将本该由浏览器处理的样式变化强塞 js 运行时反复计算。每次 css 调用传新对象导致缓存失效、重复哈希与 dom 插入;ssr 未提取关键 css 引发 fouc 和双重注入;global/keyframes 泄漏加剧内存增长;应分离动态逻辑(用 style/css 变量)与静态样式(提为常量)。

Emotion 渲染大量动态 CSS 卡顿,根本原因不是“用了 Emotion”,而是把本该由浏览器原生处理的样式变化,硬塞进 JS 运行时反复计算——每次渲染都新建对象、重复哈希、插入新规则,主线程被拖垮。
css 函数里写内联对象 = 每次都触发全量重计算
常见错误是把 props 直接塞进 css 调用里:
-
css接收一个新对象(如{ fontSize: `${size}px`, color: variant === 'primary' ? 'blue' : 'gray' }),哪怕size和variant没变,对象引用也不同 → 缓存失效 - Emotion 必须对这个对象序列化 → 生成哈希 → 查缓存 → 不命中 → 创建新 class → 插入
<style></style>标签 - 高频组件(如列表项、动画帧)每秒渲染几十次,等于每秒执行几十次 DOM 插入 + 样式解析,CPU 直接拉满
服务端没提取关键 CSS = 客户端重复注入 + FOUC
Next.js 或自建 SSR 项目若跳过服务端样式提取,会出现双重卡顿:
- 服务端返回的 HTML 不含首屏样式 → 浏览器先渲染无样式的 DOM(白屏或错位)
- 客户端 hydration 时,所有
css调用重新执行一遍 → 多余 class 堆积、<style></style>标签反复增删 - Layout thrashing 风险上升:样式注入时机不可控,可能打断浏览器的渲染流水线
- 必须用
@emotion/server的renderStylesToString()提取,并在中注入;SSR 后客户端需调用cache.reset()
全局样式或 keyframes 泄漏 = 内存缓慢增长 + 缓存污染
很多人忽略 global 和 keyframes 的生命周期管理:
-
global规则默认永不释放,主题切换或微前端卸载后仍驻留内存 -
keyframes名称若用随机 ID(如keyframes`{...}`每次调用),缓存中会存下无数份相同逻辑的不同名称规则 - 检查
cache.sheet.tags.length,持续上涨且不回落,基本可定位为全局规则泄漏 - 正确做法:
useInsertionEffect管理global注入与清理;keyframes名称必须静态、可预测(如slideIn)
真正卡顿的从来不是 Emotion 本身,而是把动态逻辑和静态结构混在同一层处理——变量该走 style,主题该走 CSS 变量,静态部分必须提成模块级常量。否则再小的按钮,渲染一百次就是一百次无意义的哈希与注入。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











