Button.module.scss导入后styles.button为undefined,因文件名非.module.scss、在Server Component中导入或JS中误用连字符类名(如styles.btn-primary应为styles.btnPrimary)。

直接用 .module.scss 就行,Next.js 13.4+ 原生支持,无需额外配置;但文件名、导入位置、类名写法三处错一点,CSS Modules 就失效,样式照样全局污染。
为什么 Button.module.scss 导入后 styles.button 是 undefined?
这不是路径问题,而是构建链路没把你的文件当模块处理。常见断点:
- 文件名是
Button.scss或Button.module.css—— 必须是.module.scss(注意双后缀) - 在 Server Component(比如未加
"use client"的page.tsx或layout.tsx)里 import —— Next.js 直接跳过解析,报Module not found - CSS 类名用了连字符,比如
.btn-primary,但 JS 中写了styles.btn-primary—— 这是 JS 语法错误(减法运算),必须写成styles.btnPrimary或styles["btn-primary"] - 全局重置样式(如
reset.scss)误命名为reset.module.scss,导致类名被哈希化,html/body样式失效
怎样在 .module.scss 里安全混用全局样式?
:global() 是唯一合法逃逸方式,但只对类、ID、属性选择器有效,且必须包裹完整选择器:
-
:global(.highlight) { color: red; }→ 编译后仍是.highlight,可被document.querySelector捕获 -
.container :global(.btn) { padding: 8px; }→.btn逃逸,但受.container局部作用域约束(推荐) -
:global(html, body) { margin: 0; }→ ❌ 无效,:global()不支持标签选择器 -
@keyframes slideIn { ... }→ ❌ 仍为全局,动画名不会被哈希,需手动加前缀或写成:global(@keyframes slideIn)
全局 SCSS 怎么引入才不和组件样式打架?
全局样式必须走根布局,且不能带 module 后缀:
立即学习“前端免费学习笔记(深入)”;
- 创建
app/globals.scss(无module),写重置、字体、工具类等 - 只在
app/layout.tsx顶部 import:import './globals.scss'—— 别在page.tsx或组件里导 - 如果用了
@use引入变量或 mixin,确保它们定义在非module文件中,否则@use会失败 - 别在
_app.tsx(Pages Router)和app/layout.tsx(App Router)里混用全局样式,两者互不感知
真正容易被忽略的是:CSS Modules 只改 class/id 选择器的类名,@font-face、@layer、自定义属性(--color-primary)全都不处理,得靠命名空间或 :global() 手动兜底。


















