使用antd和css-modules冲突的解决办法

在暑假做项目实训的时候前端就使用到React构建并且使用了Ant Design作为组件库,当时就使用了extract-text-webpack-plugin把css单独抽离出来成为一个单独的css文件并引入,当时就遇到一个问题,当我使用css-loader来处理css时,并不能处理自定义的css,但是我把CSS直接写进组件中是可行的,由于当时项目比较小并且时间比较赶,就直接使用了这种方式,在开发过程中也有苦说不清,但总算是完成了。

最近想写一点东西,又用到antd了,当然是相同的问题,只不过时过境迁,我有足够多的时间来处理这个遗留下来的问题。可是即使有那么多的时间,可是还是踩坑无数,最终还是完成了。相信遇到这个问题的并不止我一个人,这里就先记录下来,希望能对你有所帮助。

解决办法

经过查询和思考,解决这样的问题最好是单独处理antdCSS和自定义的CSS。好了问题解决办法已经很明显了,我们需要些两个不同的规则来出来css,就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader'
})
},
{
test: /\.css$/,
exclude: /node_modules/,
use: 'css-loader'
},
...
plugins: [
new ExtractTextPlugin('style.css')
]

上面的代码我建立了两规则分别处理自定义css和antd 预定义css,我们可以正常的使用import './style.css'的形式引入css,但是我们查看页面,并没有加载我们自定义的css。

好吧,既然这样再试试css-modules的方式算了,我们把第二个规则改成下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
...
{
test: /\.css$/,
exclude: /node_modules/,
use: [
loader:'css-loader',
options: {
modules: true,
localIndentName: '[local]--[hash:base64:5]'
}
]
}

现在我们可以通过import style from './style.css'的形式引入自定义css,并且通过style.className的形式给元素设置类。这次倒好,直接build不成功了,我一气之下索性不搞了;为了继续捣鼓下去,我直接又把CSS写在组件中了,直到我要使用react-transition-group来做路由切换动画,不得不倒回来解决。这次比以往更加冷静,我仔细阅读了extract-text-webpack-plugin的readme过后,恍然大悟,原来我们可以在一个项目中使用多个ExtractTextPlugin实例来生成多个css文件!好了,这次还是通过两个规则处理css,并且构建两个css文件,一个是自定义的css,一个是antd css,问题迎刃而解,又可以开心的捣鼓了!

好了,show you the code!:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractANTDCSS = new ExtractTextPlugin('[name]-antd.css');
const extractNormalCSS = new ExtractTextPlugin('[name]-normal.css');

module.exports = {
...
module:{
rules: [
{
test: /\.css$/,
include: /node_modules/,
loader: extractANTDCSS.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {modules: false}
}]
})
},
{
test: /\.css$/,
exclude: /node_modules/,
use: extractNormalCSS.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
modules: true,
localIndentName: '[local]--[hash:base64:5]'
}
}]
})
}
]
},
plugins: [
extractANTDCSS,
extractNormalCSS,
...
]
}

以上的两个loader会生成两个css文件,分别是vendor-antd.cssmain-normal.css,我们只需要在正确的位置引入这两个css文件就好了!

尾巴

我在前面提到我把CSS直接写在元素/组件的style标签中,其实这种方式实不可取的,它会让你在编码和代码review中苦不堪言,因为一旦项目变得很大,当你想修改某个样式的时候,花在定位CSS的时间是非常多的;并且,可读性和可复用性也会大打折扣;而且我们经常在写样式的过程中使用的各种选择器、伪类、伪元素都无法发挥其灵活的作用。所以,无论你是以何种方式写前端,请尽量不以这种方式写CSS。

当然,我们也要从性能上去考虑。因为css是在页面解析正式前就加载好了的(写在header)里面,在我们再解析页面的时候,加载速度就会变得更快;再有,如果我们使用把CSS写在组件中后,无可避免的会产生更多的重绘和回流,这会严重影响渲染性能。比如我们使用JS修改我们在style属性中标明的样式,那么必然会触发一次repaint。

好了,到此打住!如果你想学习reflow和repaint,点击这里,也许会帮助你!

分享到 评论