react项目使用cssModule

141 阅读1分钟

最近新建了一个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算法统一。