CSS-in-JS库默认不支持HMR,因其运行时动态注入<style>标签,而HMR仅更新JS模块,未自动清理旧样式,导致重复规则、权重混乱与样式闪动。
因为多数CSS-in-JS方案(比如 styled-components、@emotion/react)在运行时动态创建 <style> 标签并注入样式,而标准Webpack/Vite的HMR只触发JS模块更新,不会自动清理旧的动态样式块。结果就是新样式叠加在旧样式上,出现重复规则、权重混乱、甚至样式“闪动”。
color,浏览器里却看到两套同名class同时生效useEffect 里手动插入的 <style> 不会被HMR识别或卸载必须启用 babel-plugin-styled-components 的 displayName 和 ssr 配置,并配合 styled-components 自带的热更新插件。Vite用户还需额外加 vite-plugin-styled-components。
.babelrc 中确保有 {"plugins": ["babel-plugin-styled-components"]}
FAST_REFRESH=true 环境变量(尤其CRA 4+)StyleSheet.reset() —— 它会清空所有样式,包括第三方UI库的const Button = styled.button),匿名箭头函数无法被HMR追踪@emotion/react 的热重载依赖 @emotion/babel-plugin 插件和 emotion 包内置的 cache 清理机制,但默认只在开发模式下启用。漏掉任何一环都会让HMR静默失效。
@emotion/babel-plugin,且 sourceMap 设为 true
createEmotionCache 或 CacheProvider 没有被封装成全局单例 —— HMR需要每次重新创建cache实例css 模板字符串里写变量计算逻辑(如 css`margin: ${x * 2}px`),这类表达式会让HMR无法比对样式变更@emotion/react + @emotion/babel-plugin,并确认 vite.config.ts 中未禁用 esbuild.jsxInject
如果你手写了一个轻量级CSS-in-JS工具(比如基于 CSSStyleSheet.insertRule),HMR就得自己接管样式清理逻辑 —— 没有现成插件兜底。
立即学习“前端免费学习笔记(深入)”;
module.hot.dispose 卸载对应 <style> 或清除 CSSStyleSheet 中的规则CSSStyleSheet.replaceSync,得回退到 textContent 替换整个标签内容:root { --color: red }),HMR更新后要手动触发 document.documentElement.style.setProperty 同步真正卡住人的往往不是“怎么开”,而是“旧样式没清干净”。HMR只是触发器,样式生命周期管理还得自己兜住。