• [转] 使用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就行。

  • 相关阅读:
    PC远程调试设备(转)
    根据自己的需要,把别人开发好的东西搬过来,优化and重构,在优化的过程中,甚至也会弄出一套全新的东西(转)
    修改Hosts不生效的一个场景-web 专题
    Data URI(转)
    数据仓库与数据挖掘的一些基本概念
    几种常见模式识别算法整理和总结
    史上最简单的Hibernate入门简单介绍
    sprintf,你知道多少?
    一步一步写算法(之洗牌算法)
    ListView的优化
  • 原文地址:https://www.cnblogs.com/chris-oil/p/9025356.html
Copyright © 2020-2023  润新知