css modules 在 gatsby 中默认开箱即用,只需文件名以 .module.css 结尾即可启用局部作用域;webpack 仅匹配 /\.module\.css$/ 规则,普通 .css 文件仍为全局样式,类名不哈希、不可通过 styles.xxx 导入,且不支持 .module.scss 或 .module.styl(需对应插件)。

CSS Modules 在 Gatsby 中默认开箱即用,无需插件或额外配置——只要文件名以 .module.css 结尾,Gatsby 就会自动启用作用域处理。
为什么 .module.css 文件名是硬性要求
文件扩展名是 Gatsby 识别 CSS Modules 的唯一依据。Webpack 规则只匹配 /\.module\.css$/,普通 .css 文件会被当作全局样式处理,类名不会被哈希化,也无法通过 JS 对象导入。即使内容完全一样,Button.css 和 Button.module.css 的行为天差地别。
- 错误写法:
import styles from "./Button.css"→styles是空对象(开发模式下可能报 warning) - 正确写法:
import styles from "./Button.module.css"→styles.button返回类似"Button__button__abc123"的稳定类名 - 注意:不支持
.module.scss或.module.styl——它们需要对应插件(如gatsby-plugin-sass)显式开启 Modules 支持
import 后的类名对象不是运行时生成的
Gatsby 在构建阶段就将 .module.css 编译为带哈希的类名,并生成对应的 JS 模块导出。这意味着:
- 类名在开发和生产环境保持一致(除非 CSS 内容变更),利于无障碍测试和 E2E 断言
- 不能动态拼接类名字符串再访问,例如
styles["button" + variant]会返回undefined;必须在编译前明确写出所有用到的类名 - 支持解构导入:
const { button, primary } = styles,但解构后的变量名与原始 CSS 类名强绑定
如何与全局样式共存且避免冲突
一个 Gatsby 项目通常混合使用全局 CSS(如重置、字体定义)和组件级 .module.css。关键在于加载顺序和作用域隔离:
- 全局 CSS(
import "./global.css")会注入,影响整个页面;它能覆盖.module.css中同名选择器,因为后者实际生成的是带哈希的高 specificity 类名(如.Button__title__xyz789),而非简单.title - 不要在
.module.css中用:global(.some-class)随意穿透——这会破坏模块边界,仅在极少数需对接第三方 UI 库时谨慎使用 - 若需复用全局语义类(如
text-lg),建议用 PostCSS 插件(如postcss-preset-env)配合gatsby-plugin-postcss,而不是把 Tailwind 类直接写进.module.css
容易被忽略的调试细节
开发时看到的类名(如 Button__button__abc123)看似随机,但它的生成逻辑有迹可循:
- 类名哈希基于文件路径 + 原始类名 + CSS 内容(不含注释),所以修改任意一项都会触发新哈希
- 若发现两个组件的相同类名(如
title)生成了不同哈希,说明它们来自不同.module.css文件——这是预期行为,也是作用域隔离的体现 - 生产构建中,Gatsby 默认启用 CSS 压缩和 contenthash 文件名(
styles.[contenthash].css),但.module.css的类名哈希不受此影响,仍由上述规则决定
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











