[转] 使用babel-plugin-react-css-modules简化CSS Modules的使用

在咱们的产品中,均使用CSS Modules来做为样式解决方案,大体的代码是这样的:javascript

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>; } } 

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

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

babel-plugin-react-css-modules插件能够必定程度上缓解这些问题,使代码变为:java

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的语法node

调整构建配置

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

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

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配置修改一下,对应至项目根目录就行。web

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

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'npm

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

相关文章
相关标签/搜索