css-loader插件中modules详解

1,665 阅读3分钟

配图专用

优雅的使用:global解决模块样式的全局定义

问题背景:

很多时候在项目中我们需要把css进行模块化,以此形成css作用域,来避免css的一些冲突。这个时候最好的就是应用webpack中的css-loader模块对css进行解析模块化。但是在项目中经常会使用到第三方组件(例如antd等),我们又需要对这些组件进行样式修改,满足自身需求。此刻,你可能首先想到以下方法来进行处理:

  • 通过配置less模块化将antd样式类统统模块化
  {
    loader: 'css-loader',
    options: {
      importLoaders: 2,
      modules: {
        getLocalIdent: getCSSModuleLocalIdent // react-dev-utils提供
      }
    }
  }
  • 不对antd样式模块化,直接修改全局样式,修改antd样式
<!--直接进行antd样式定义-->
.ant-tabs-nav .ant-tabs-tab {
  width: 140px;
  text-align: center;
  border-top: 2px solid transparent;
}

然而,这样第一种是无法取到相应的类,第二种是会影响全局。

css-loader中modules参数项scope

scope中有两个选项:local和global,local代表的就是模块化模式,global代表的就是全局。当css-loader不设置modules时候,scope默认设置为global,反之,为local。

  1. 设置scope: local情况下
<!--css-loader官方例子说明-->

:local(.className) { background: red; }
:local .className { color: green; }
:local(.className .subClass) { color: green; }
:local .className .subClass :global(.global-class-name) { color: blue; }
转化成:
._23_aKvs-b8bW2Vg3fwHozO { background: red; }
._23_aKvs-b8bW2Vg3fwHozO { color: green; }
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 { color: green; }
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name { color: blue; }
注意:添加global的.global-class-name的类未被模块化,添加local的className被模块化。(这里最好使用驼峰式定义类名)

再看下现实中的代码块:

<!--.content类是放在main.scss文件下,采用sass进行预解析的-->
<!--antd样式全局修改,不会影响到其他文件里面的antd样式(可以看下面转化之后样式)-->
<!--采用{}对象式定义可以一次定义好几个类-->
<!--这样定义的类不会被模块化解析保持antd的原类名-->
.content {
  .test {
    text-decoration: underline;
  }
  :global {
    .ant-tag {
      color: red;
    }
    .ant-table-thead {
      th {
        font-weight: bold !important;
      }
    }
  }
  <!--也可以采用函数式可以单独定义某个样式-->
  :global(.ant-tag) {
    color: blue;
  }
 }
 
 转化成:
 
 .main_content__1rULD .ant-tag {
   color: red;
 }
 .main_content__1rULD .ant-table-thead th {
   font-weight: bold !important;
 }
  1. 设置scope: global:
    即不进行模块化编译css,直接设置modules:false即可。

其他的解决方法

可以在在需要修改的父类元素上定义标识性class名(非模块化定义),再以此类目作为css选择器的父选择器,以此来进行antd样式限定,不冲突。

<!--这个filter就是限定子元素antd父类-->
<!--html-->
<div className={`${styles.filters} filter`}>
  <!--some antd codes...-->
</div>

<!--antd-reset.css-->
<!--定义全局antd样式,此文件不进行css的modules处理:modules: false-->
.filter .ant-select-selector {
  color: #fff;
}

结尾

总结下:前端是个很细的活,很多解决方法都在api文档里躺着,但是不经过细嚼烂咽,还是很难实践好文档编写者的意图,毕竟文档编写者只是站在他已掌握的角度去写文档,所以还是需要我们自己多在代码里实现几遍,会发现更多的实用方法。