都能看懂的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