likes
comments
collection
share

css moudles是什么,怎么用,来,保证给你讲透了👊

作者站长头像
站长
· 阅读数 12

没有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,
        },
      },
    ],
  },
};

这是最简单的开启方法(配置内容省略了不必要的内容,文章末尾有完整的配置项)

测试:

现在有个h1tag,设置了它的背景颜色。组件内容:css moudles是什么,怎么用,来,保证给你讲透了👊样式文件内容:css moudles是什么,怎么用,来,保证给你讲透了👊页面显示效果:css moudles是什么,怎么用,来,保证给你讲透了👊浏览器中的F12,还是和编辑器中的一样css moudles是什么,怎么用,来,保证给你讲透了👊


现在开启css modules样式文件不用修改,只需要修改组件内容即可。修改组件导入样式的方式:css moudles是什么,怎么用,来,保证给你讲透了👊css moudles是什么,怎么用,来,保证给你讲透了👊引入样式需要用esmodule的形式重启项目:npm run start页面显示效果:css moudles是什么,怎么用,来,保证给你讲透了👊我们看看浏览器中的类名:css moudles是什么,怎么用,来,保证给你讲透了👊可以看到所有的类名都变成了随机的唯一值

测试成功,确实拥有了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 = icssicss 只会编译底层的 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变量一样使用

localIdentNamelocalIdentContext

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"],
      },

    ],
  },
};
  1. 这里将module css和普通css分开来处理,这样module.css后缀文件就是局部作用域,css后缀就是全局作用域。就不用mode来区分作用域了
  2. module css中只留下了localIdentName用来设置唯一化css类名的命名,还留下了exportLocalsConvention,用来设置组件中导出类名样式--驼峰。驼峰的样式更切近于js的变量命名。
  3. 还有中最简单的配置,直接把modules设为true就可以了,然后其他的一切功能都是默认的(导出的类名驼峰也没有了)

总结:

这篇文章简单介绍了css modules在webpack中如何配置,顺带介绍了css loader的配置项和最佳实践。不得不说,这些配置项还挺没有用的,也许只是为了配置的时候更灵活吧。我还是喜欢那些功能单一的工具,使用简单的易上手的,像锤子,铲子,水果刀,都是功能单一的css moudles是什么,怎么用,来,保证给你讲透了👊css moudles是什么,怎么用,来,保证给你讲透了👊css moudles是什么,怎么用,来,保证给你讲透了👊

而不是像瑞士军刀一样,一个刀即可以作为刀,也可以作为剪子,锯子,也可以作为开瓶器css moudles是什么,怎么用,来,保证给你讲透了👊金友们怎么看呢?