2021.11.29 每天进步一点点:用你懂的方法,说说css-modules

都能看懂的css-modules

        • 前言
          • 开发工具版本
        • webpack配置
          • 准备工作
          • 暴露webpack配置
          • 在dev环境的配置
          • 在生产模式的配置
        • css-modules怎么用
        • styles是什么
        • css-modules是啥
          • 释义
          • 引入
          • 命名
          • 作用域转换
          • 组合使用
        • 打包
        • 参考文档

前言

之前用react做开发时,简单用过css-modules 。但是也只是简单用过,并不了解。

以我浅薄的知识来说,我一直以为css-modules是一个库,或者是react绑定的一个插件。

然而, 都不是。 它只是css-loader中的一个功能罢了。

在需要用到时,再去开启。 当然, 这需要用到webpack配置项。

提到webpack,不要慌,因为配置确实很简单。后续内容会逐步解释。

以下将根据css-nodules在github的文档、并伴随demo进行解释。

开发工具版本
  • react: ^17.0.2
  • webpack: 1.14.0 (写博客的时候才发现是1.0版本…)
  • webpack-dev-server: 1.16.2

webpack配置

抛开实践而讨论问题本身,就是耍流氓。

所以,要想从实际意义上了解,就必须先会用。

要使用,就必须先做webpack配置。

css-modules依赖的是css-loader。 换句话说,要使用css-modules,就需要在css-loader中开启。

注意:本文只说明在react中的应用和配置,在其他框架中的使用方法,请参考最下方官方文档。(不清楚在其他框架中是否也这么用的…)

准备工作

css-modules是依赖css-loader的, 而css-loader又依赖style-loader ,所以,

如果未安装loader,需要先安装:

npm install css-loader --save

npm install style-loader --save

暴露webpack配置

webpack配置在react中是封装起来的。

需要运行npm run eject

把配置暴露出来。

运行后,是这样的文件结构:

在这里插入图片描述
/config下有两个webpack配置文件:

webpack.config.dev.js 对应开发环境的配置

webpack.config.prod.js 对应生产环境的配置

在dev环境的配置

/config/webpack.config/dev.js中找到这一段配置:

{test: /\.css$/,loader: 'style!css?importLoaders=1!postcss'},

把loader替换成如下配置:

{test: /\.css$/,loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',},

这一段配置的意思是:

开启样式模块化,在css-loader 之后指定1个数量的loader(即 postcss-loader)来处理import进来的资源,把类名转换成css文件名__类名__哈希值取base64编码的前五位

举个例子:

在index.css文件中,写一个类名为color的类:
在这里插入图片描述

转换后,类名变成了这样:
在这里插入图片描述

在生产模式的配置

在生产模式下,同样需要配置,

来到/config/webpack.config.prod.js进行配置:

找到这一段代码:

{test: /\.css$/,loader: ExtractTextPlugin.extract('style','css?importLoaders=1!postcss',extractTextPluginOptions)// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.},

更改成如下:

{test: /\.css$/,loader: ExtractTextPlugin.extract('style-loader','css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader',)// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},

再往下找,可以看到这个配置,更改后如下:

new ExtractTextPlugin('style.css', { allChunks: true }),

这一步配置的意思是:

提出css样式,打包后放在style.css样式文件里。

allChunks设置为true,意思是异步css样式也会提取。

执行npm run build之后, 就可以看到提取到的文件了:

在这里插入图片描述

好了。 到这一步, 配置完成。 准备工作,初步做好。

看着写了那么长,其实总共就改了三行代码(*_^)


css-modules怎么用

先会用,再深入原理。 这是我的方法。

好处是, 可以一步步获取成就感, 学习兴趣更加。

在做深入了解后,能有更强的代入感。

不然的话,学了半天,不会用,感觉啥都不会, 肯定就扔一边去了23333…

我们来写个例子:

/src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import styles from './index.css'; // 引入样式function App() {console.log('styles-0: ', styles);return (<div>// 使用样式<h3 className={styles.color}>hello react!</h3></div>)
}ReactDOM.render(<App />document.querySelector('#root')
);

/src/index.css

.color {color: red;
}

启动项目npm start

这时候就可以看到这样的效果:

在这里插入图片描述

可以看出,这里应用可以分为三步:

1, 写css样式。 就像我们平时写css一样。2,引入样式
import styles from './index.css';3,用样式
className={styles.color}

写法和应用都很符合日常的开发,不会有什么不适应。


styles是什么

看了上面的例子, 肯定会有这么一问:

styles是什么?

为什么引入的是styles?

className后面不是应该用'color'形式吗?

回头看上面的例子,我们在/src/index.js文件里,预留了一个打印语句:

console.log('styles-0: ', styles);

打开控制台,可以看到如下结果:

在这里插入图片描述
我们引入的文件,变成了styles对象,

对象的属性是我们自己写的类名,

属性的值是新生成的一个类名。

当我们用styles.color时,对应的结果就是新生成的类名。

这样有个好处,

就是我们需要用到哪个类名,就styles.类名即可。

不需要的类名,我们就可以不调用。

再看下标签里的类名是什么:

在这里插入图片描述

可以看到,标签里是通过webpack编译后生成的新类名了。

看到这里, 我们肯定对css-modules有一定的了解了。

那么,它到底是什么? 又是用来做啥的呢?


css-modules是啥
释义

根据官方文档:A CSS Module is a CSS file in which all class names and animation names are scoped locally by default 。 简而言之,一个css模块就是把所有类名和动画名,都放到一起形成局部范围样式的文件。

比如上面说的index.css就是被当作一个css模块进行引入的,生成了一个styles对象。

既然是模块化, 那么就可以引入。

引入

它有两种引入形式:

  • import styles from 'index.css'

  • url(...)

被当作模块引入后, 就会形成一个包含模块内所有样式的对象。 比如上面例子中的styles

命名

官方文档建议我们用驼峰命名法来给类名命名

比如.showWrap

主要是因为, 这些类名被引入后,都是放在一个对象里的。

我们要是调用对象里的属性,习惯于obj.aB

而不喜欢这样调用obj['a-b']对吧。

作用域转换

把局部作用域转换成全局作用域:

:global(类名)

如果是动画名称要转换为全局,可以这么用:

@keyframes:global(xxx)

把全局类名转换成局部类名:

:local(类名)

组合使用

语法:composes: xxx from './style.css'

写个demo验证一下:

还是用上面的例子,

我们再同样目录下,写一个index1.css

.backColor {background-color: darkkhaki;
}

index.css中进行组合使用:

.color {color: red;composes: backColor from './index1.css';
}

查看结果:

在这里插入图片描述

可以看到, 背景颜色发生了变化。 组合效果起了作用。


打包

用法和语法已经有了基本了解,

可以试着打包一下,

执行npm run build

可以看到生成的/build文件夹结构:

在这里插入图片描述


参考文档
  • css-modules in github: https://github.com/css-modules/css-modules
  • css-modules-webpackdemo for dev: https://github.com/css-modules/webpack-demo
  • css-modules-webpack prod: https://github.com/css-modules/webpack-demo/blob/master/webpack.config.js
  • https://www.ruanyifeng.com/blog/2016/06/css_modules.html