css moudles是什么,怎么用,来,保证给你讲透了👊
没有CSS modules的项目是什么样的
样式是全局的,组件内部会导致样式冲突。多个项目更是会有冲突。这个就不举例子了。
当然css module只是解决问题的一种方式,还有其他的解决方案
在React脚手架中怎么用
如果不是脚手架,如何使用
不看这篇文章也不影响理解
现在开始修改webpack配置文件,主要修改css-loader的module对象,那么将moudle属性变成true,就有用了css module的能力了
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
},
],
},
};
这是最简单的开启方法(配置内容省略了不必要的内容,文章末尾有完整的配置项)
测试:
现在有个h1
的tag
,设置了它的背景颜色。组件内容:样式文件内容:
页面显示效果:
浏览器中的F12,还是和编辑器中的一样
现在开启css modules样式文件不用修改,只需要修改组件内容即可。修改组件导入样式的方式:引入样式需要用esmodule的形式重启项目:
npm run start
页面显示效果:我们看看浏览器中的类名:
可以看到所有的类名都变成了随机的唯一值
测试成功,确实拥有了css module的能力
使用上和在React脚手架开发一致,分为局部类名,全局类名啊什么的。就是有一点不同,我这个配置是所有的css
文件都开启了css modules的能力,而React脚手架之针对module.css
后缀的文件开启css modules
我们当然可以做到和react脚手架一致。直接跳到文章末尾,你可以得到答案。
css lodaer其他功能
- modules有很多可以的值类型, 允许的类型有
Boolean
|String
|Object
默认值:undefined
下面是不同类型情况下,css loader对css文件做的处理
undefined
为所有匹配 /.module.\w+/i.test(filename)与/i˙css\w˙+/i.test(filename) 与 /\.icss\.\w+/i.test(filename)与/i˙css\w˙+/i.test(filename) 正则表达式的文件启用 CSS 模块
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: undefined,
},
},
],
},
};
true
对所有文件启用 CSS Modules
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
},
],
},
};
false
对所有文件禁用 CSS Modules
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: false,
},
},
],
},
};
string
启用CSS Modules,并且设置css modules的模式
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
// 使用 `local` 同使用 `modules: true` 的效果是一样的
modules: "global",
},
},
],
},
};
string类型可能的值有:
modules =
| "local"
| "global"
| "pure"
| "icss"
| ((resourcePath: string) => "local" | "global" | "pure" | "icss");
modules = local
表示所有的css文件都是局部作用域,类名都会被重新生成唯一的随机类名,要想使用全局作用域类名,就需要:global()
像这样:
.className {
color: green;
}
:global(.global-class-name) {
color: blue;
}
这是两个普通的类名,一个是局部作用域,一个是全局作用域,当该文件被处理之后会变成下面这样:
._23_aKvs-b8bW2Vg3fwHozO {
color: green;
}
.global-class-name {
color: blue;
}
可以看到全局类名并没有被处理,这样就保持了原有的全局属性
modules = global
表示所有css文件都是全局类型,要想使用局部作用域的类名,就用:local()
声明,像这样:
:local(.local-class-name) {
background: red;
}
.class-name {
color: blue;
}
经过css modules处理后就变成了这样:
._23_aKvs-b8bW2Vg3fwHozO {
color: green;
}
.global-class-name {
color: blue;
}
结果虽然和上面一样,但意义不一样,即局部作用域需要单独声明module = icss
,icss
只会编译底层的 Interoperable CSS
格式,用于声明 CSS 和其他语言之间的:import
和 :export
依赖关系。 意思就是说,ICSS 提供 CSS Module 支持,并且为其他工具提供了一个底层语法,以实现它们自己的 css-module 变体。如果css lodaer有前置loader--sass loader,就可以设置这个值。(react脚手架中就是这么配置的)modules = pure
pure是什么意思我也不清楚,文档也没有,就没研究了
object
- modules可以是一个object,来进行更详细的配置
//webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
mode: "local",
auto: true,
exportGlobals: true,
localIdentName: "[path][name]__[local]--[hash:base64:5]",
localIdentContext: path.resolve(__dirname, "src"),
namedExport: true,
exportLocalsConvention: "camelCase",
},
},
},
],
},
};
mode
:
和modules的string类型的值一致,含义和作用也一致。用来区分css文件是全局的,还是局部的
auto
:
有效值:
undefined
- 为所有文件启用 CSS 模块。true
- 为所有匹配/\.module\.\w+$/i.test(filename)
和/\.icss\.\w+$/i.test(filename)
正则表达式的文件启用 CSS 模块。false
- 禁用 CSS 模块。RegExp
- 为所有匹配/RegExp/i.test(filename)
正则表达式的文件禁用 CSS 模块。function
- 为所有通过基于文件名的过滤函数校验的文件启用 CSS 模块。
简单来说就是可以更细致地自定义,决定哪些文件是css module,哪些文件不是
exportGlobals
:
类型:Boolean 默认:false
允许 css-loader 从全局类或 ID 导出名称,因此您可以将其用作本地名称。简单来说,就是允许全局作用域css文件也可以像局部作用域css moudles那样用js变量代替css类名。
这样设置是因为全局css文件不能像js变量一样使用
localIdentName
和localIdentContext
localIdentName支持的模板字符串:
- [name] 源文件名称
- [folder] 文件夹相对于 compiler.context 或者 modules.localIdentContext 配置项的相对路径。
- [path] 源文件相对于 compiler.context 或者 modules.localIdentContext 配置项的相对路径。
- [file] - 文件名和路径。
- [ext] - 文件拓展名。
- [hash] - 字符串的哈希值。基于 localIdentHashSalt、localIdentHashFunction、localIdentHashDigest、localIdentHashDigestLength、localIdentContext、resourcePath 和 exportName 生成。
- [:hash::] - 带有哈希设置的哈希。
- [local] - 原始类名。
建议:
- 开发环境使用 '[path][name]__[local]'
- 生产环境使用 '[hash:base64]'
这两者都是用来设置css类名会用到的,我们知道css modules是会将css 类名变成全局唯一的,那么使用localIdentName
就可以控制全局唯一的类名样式。localIdentContext
则是用来配置[folder]
的相对路径
namedExport
:
本地环境启用/禁用 export 的 ES 模块。会和exportLocalsConvention
的值挂钩
默认就是支持esmodule的,感觉没啥用
exportLocalsConvention
:
类型:String|Function 默认:取决于 modules.namedExport 选项值,如果为 true 则对应的是 camelCaseOnly,反之对应的是 asIs
名称 | 类型 | 描述 |
---|---|---|
'asIs' | {String} | 类名将按原样导出。 |
'camelCase' | {String} | 类名将被驼峰化,原类名不会从局部环境删除 |
'camelCaseOnly' | {String} | 类名将被驼峰化,原类名从局部环境删除 |
'dashes' | {String} | 类名中只有破折号会被驼峰化 |
'dashesOnly' | {String} | 类名中破折号会被驼峰,原类名从局部环境删除 |
camelCaseOnly
表示只能驼峰导出,不能用原先的类名file.css:
.class-name {
}
file.js:
import { className } from 'file.css';
import fileCss from 'file.css';
这就是驼峰导出如果使用了camelCaseOnly
,那么访问fileCss['class-name']
, 会得到undefined
。但使用camelCase
就不会。
最佳实践
上面介绍了modules的配置项,相信大家对如何配置css modules有了一定的了解,下面来看看配置css modules的最佳实践
//webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.moudle\.css$/i,
use:["style-loader",
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[path][name]__[local]--[hash:base64:5]",
exportLocalsConvention: "camelCase",
},
}
}, "sass-loader"]
},
{
test: /\.css$/i,
use:["style-loader", "css-loader", "sass-loader"],
},
],
},
};
- 这里将module css和普通css分开来处理,这样
module.css
后缀文件就是局部作用域,css
后缀就是全局作用域。就不用mode
来区分作用域了 - module css中只留下了
localIdentName
用来设置唯一化css类名的命名,还留下了exportLocalsConvention
,用来设置组件中导出类名样式--驼峰。驼峰的样式更切近于js的变量命名。 - 还有中最简单的配置,直接把modules设为true就可以了,然后其他的一切功能都是默认的(导出的类名驼峰也没有了)
总结:
这篇文章简单介绍了css modules在webpack中如何配置,顺带介绍了css loader的配置项和最佳实践。不得不说,这些配置项还挺没有用的,也许只是为了配置的时候更灵活吧。我还是喜欢那些功能单一的工具,使用简单的易上手的,像锤子,铲子,水果刀,都是功能单一的
而不是像瑞士军刀一样,一个刀即可以作为刀,也可以作为剪子,锯子,也可以作为开瓶器金友们怎么看呢?
转载自:https://juejin.cn/post/7269290896214425634