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,还是和编辑器中的一样
浏览器中的F12,还是和编辑器中的一样
现在开启css modules样式文件不用修改,只需要修改组件内容即可。修改组件导入样式的方式:
 引入样式需要用esmodule的形式重启项目:
引入样式需要用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




