也许 CSS 最重要的挑战是所有规则都存在于全局范围内,这意味着两个具有相同名称的 class 将发生冲突。CSS 本身拥有一些限制办法,但对于一个项目来说,还可以有其他的办法。CSS Modules 为每一个模块都启用了局部作用域,其做法是为每一个声明的 class 名称加上全局唯一的哈希值。
通过 css-loader 使用 CSS Modules
Webpack 的 css-loader 支持 CSS Modules。您可以通过 loader 定义来启用它:
{
use: {
loader: "css-loader",
options: {
modules: true,
},
},
},
完成此更改后,您的 class 定义将拥有局部作用域。如果您需要定义全局 class,则需要将它们包含在类似 :global(.redButton) { ... }
的声明类型中。
现在,使用 import
语句导入样式并在组件上应用局部 class。假设你有 CSS 如下:
app/main.css
body {
background: cornsilk;
}
.redButton {
background: red;
}
然后,您可以在组件中使用 class:
app/component.js
import styles from "./main.css";
...
// 使用 class
element.className = styles.redButton;
body
依然具备全局作用域,这就是 redButton
的不同之处。您可以构建特定于组件的样式,这些样式不会以其他方式泄漏。
CSS Modules 提供了诸如组合之类的附加功能,以便更轻松地使用您的样式。只要在 css-loader 之前应用它们,您也可以将它与其他 loader 结合使用。
可以按照官方文档中的说明修改 CSS 模块的行为。例如,您可以控制它生成的名称。
eslint-plugin-css-modules 可以方便地跟踪 CSS 模块相关的问题。
将 CSS Module 与第三方库以及标准 CSS 一起使用
如果您在项目中使用 CSS 模块,则应该通过单独的 loader 来处理标准 CSS,而不启用_css-loader_ modules
选项。否则,所有的 class 都将启用局部作用域。对于第三方库来说,这几乎肯定不是您想要的。
您可以针对 node_modules 目录来设定 include
规则,以不同方式处理第三方 CSS,从而解决这个问题。或者,您可以针对 css 模块启用特定的文件扩展名(.mcss
),然后通过 test
匹配 css 模块,再通过 loader 对此进行处理。
总结
CSS 模块通过默认为每个文件的提供局部作用域来解决 CSS 的全局作用域问题。您仍然可以拥有全局样式,但需要额外的努力。如上所示,可以轻松地设置 Webpack 以支持 CSS 模块。