最近新建了一个react项目,想加上cssModule进行样式隔离。如下:
通过拼接[文件名]__[类名]-[hash]生成一个唯一值,保证了样式不会冲突。
实现过程如下:
1、创建index.js文件,文件的内容:
export default function Test(){
return <div styleName='test'></div>
}
这里我们用styleName来定义类型,之后再说为什么。
2、创建index.cssmodule.styl文件,问价的内容为:
.test
color red
该文件为.styl后缀,因为使用stylus做预处理器。
3、配置webpack
const genericNames = require('generic-names');
const localIdentName = '[name]__[local]-[hash:base64:5]';
const generateScope = genericNames(localIdentName, { context: process.cwd(),});
.......
rules: [
{
test: /\.styl/i,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
getLocalIdent: (
{ resourcePath },
localIdentName,
localName,
) => {
return generateScope(localName, resourcePath);
},
},
},
},
'stylus-loader',
],
},
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
include: [path.resolve('./src/')],
presets: ['@babel/env', '@babel/preset-react'],
plugins: [
'@babel/plugin-syntax-dynamic-import',
[
'babel-plugin-react-css-modules',
{
filetypes: { '.styl': { syntax: 'sugarss' } },
webpackHotModuleReloading: true,
generateScopedName: genericNames(
'[name]__[local]-[hash:base64:5]'
),
handleMissingStyleName: 'warn',
exclude: '.css$',
},
],
],
},
},
}
],
.....
这里在css-loader的rule规则中配置modules,开启cssModule,并配置类型的生成方式,生成的规则为[name]__[local]-[hash:base64:5],计算hash的是generic-names库。此时开启了css的编译,但是js的还没有开启。
在babel-loader的options中配置babel-plugin-react-css-modules,并且将generateScopedName的值为genericNames('[name]__[local]-[hash:base64:5]')。这里文件的生成规则也是[name]__[local]-[hash:base64:5],hash值也是用genericNames生成的,如果不这样做,css编译之后的类名和js的类型的hash会生成不一致。这是因为css-loader在6.2.0之后,计算hash的算法就改变了,所以要将css和js的hash算法统一。