zoukankan      html  css  js  c++  java
  • [转] 使用babel-plugin-react-css-modules简化CSS Modules的使用

    在我们的产品中,均使用CSS Modules来作为样式解决方案,大致的代码是这样的:

    import React from 'react';
    import styles from './table.css';
    
    export default class Table extends React.Component {
      render () {
        return <div className={styles.table}>
          <div className={styles.row}>
            <div className={styles.cell}>A0</div>
            <div className={styles.cell}>B0</div>
          </div>
        </div>;
      }
    }
    

    但这里显然存在一些细节上的麻烦:

    1. 引入样式时额外增加了一个styles变量
    2. 需要不断写styles.xxx,重复代码

    babel-plugin-react-css-modules插件可以一定程度上缓解这些问题,使代码变为:

    import React from 'react';
    import './table.css';
    
    export default class Table extends React.Component {
      render () {
        return <div styleName='table'>
          <div styleName='row'>
            <div styleName='cell'>A0</div>
            <div styleName='cell'>B0</div>
          </div>
        </div>;
      }
    }
    

    难点

    1. 我们的产品使用LESS而非原生的CSS来编写样式
    2. 为了生成的类名更漂亮,我们使用CSS Modules用了一个自定义的getLocalIdent实现
    3. 与webpack的整合可能存在一些难点

    解决方案

    安装依赖

    npm i --save babel-plugin-react-css-modules
    npm i --save-dev postcss-less
    

    需要注意的是,babel-plugin-react-css-modules有一个运行时依赖,所以用--save安装比较好。而postcss-less则用于解析LESS的语法

    调整构建配置

    因为有一个自定义的生成类名的函数,所以原有的.babelrc的JSON格式已经不够了(无法表达函数),因此我们要把.babelrc的配置移到babel-loaderoptions里去

    在完成移动后,再向其中添加babel-plugin-react-css-modules这一插件,在这个过程中将生成类名的函数抽象出来:

    const generateScopedName = (name, filename) => {
        const hash = hasha(filename + name, {algorithm: 'md5'});
        const basename = path.basename(filename, '.less');
        return `${dashCase(basename)}-${name}-${hash.slice(0, 5)}`;
    };
    
    exports.babel = {
        loader: 'babel-loader',
        options: {
            cacheDirectory: true,
            presets: [
                // ...预置集
            ],
            plugins: [
                // ...其它插件
                [
                    'react-css-modules',
                    {
                        context: path.join(__dirname, '..'),
                        exclude: 'node_modules',
                        filetypes: {
                            '.less': {
                                syntax: 'postcss-less'
                            }
                        },
                        generateScopedName: generateScopedName
                    }
                ]
            ]
        }
    };
    

    以上文件为webpack/loaders.js,相关的配置基本不用修改,原样使用就行。如果这些代码的位置不同,将其中的context配置修改一下,对应至项目根目录就行。

    然后调整一下CSS Modules相关的loader的配置,复用generateScopedName函数:

    exports.cssModules = {
        loader: 'css-loader',
        options: {
            sourceMap: development,
            modules: true,
            importLoaders: true,
            camelCase: 'dashes',
            getLocalIdent({resourcePath}, localIdentName, localName) {
                return generateScopedName(localName, resourcePath);
            }
        }
    };
    

    修改一些源码

    需要特别注意:所有从.js中引用.less的代码,都不可以依赖webpack的resolve.modules配置,只能写相对路径了。即原来写import 'common/less/global.less'要改成import './common/less/global.less'

    随后按着喜好将已经用了className的地方慢慢改成styleName就行。

  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/chris-oil/p/9025356.html
Copyright © 2011-2022 走看看