在我们的产品中,均使用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就行。

[转] 使用babel-plugin-react-css-modules简化CSS Modules的使用的更多相关文章

  1. css模块化及CSS Modules使用详解

    什么是css模块化? 为了理解css模块化思想,我们首先了解下,什么是模块化,在百度百科上的解释是,在系统的结构中,模块是可组合.分解和更换的单元.模块化是一种处理复杂系统分解成为更好的可管理模块的方 ...

  2. Angular Vue React 框架中的 CSS

    框架中的 CSS Angular Vue React 三大框架 Angular Vue 内置样式集成 React 一些业界实践 Angular Angular . js (1.x):没有样式集成能力 ...

  3. 重温 Webpack, Babel 和 React

    开始之前 在书写文章之前,我假设大家已经有了 JavaScript,Node 包管理工具,Linux 终端操作 这些基本技能,接下来,我将一步一步指引大家从头搭建一个 React 项目 最终实现的效果 ...

  4. 使用webpack、babel、react、antdesign配置单页面应用开发环境

    这是Webpack+React系列配置过程记录的第一篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...

  5. webpack+babel+ES6+react环境搭建

    webpack+babel+ES6+react环境搭建 步骤: 1 创建项目结构 注意: 先创建一个项目目录  react  这个名字自定义,然后进入到这个目录下面 mkdir app //创建app ...

  6. babel plugin和presets是什么,怎么用?

    https://www.fullstackreact.com/articles/what-are-babel-plugins-and-presets/ 当开发react或者vuejs app时,开发者 ...

  7. React项目 - 几种CSS实践

    前言团队在使用react时,不断探索,使用了很多不同的css实现方式,此篇blog总结了,react项目中常见的几种css解决方案:inline-style/radium/style-componen ...

  8. 经验分享:使用 Restyle.js 简化 CSS 预处理

    Andrea Giammarchi的restyle.js是一个新的,基于JavaScript的CSS预处理器,能够运行在服务端(通过Node.js)或者浏览器中.它宣称自己是“一种简化的CSS方法”, ...

  9. Webpack 2 视频教程 012 - 理解Webpack 中的 CSS 作用域与 CSS Modules

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  10. 简单 babel plugin 开发-使用lerna 工具

    babel在现在的web 应用开发上具有很重要的作用,帮助我们做了好多事情,同时又有 比较多的babel plugin 可以解决我们实际开发上的问题. 以下只是学习下如果编写一个简单的babel pl ...

随机推荐

  1. mlock实现原理及应用【转】

    转自:https://blog.csdn.net/yiyeguzhou100/article/details/78085857 https://wenku.baidu.com/view/e25b4af ...

  2. 【Linux】Swap与Memory

    背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级.所以,程序和数据如果在内存的话,会有非常快的读写速度.但是,内存的造价是要高于磁盘的,且内存的断电丢失数据也 ...

  3. 2018 Multi-University Training Contest - Team 1 题解

    Solved A HDU 6298 Maximum Multiple Solved B HDU 6299 Balanced Sequence Solved C HDU 6300 Triangle Pa ...

  4. Mybatis--01

    mybatis 封装jdbc访问代码的一个框架 (hibernate)  ORM对象关系映射 SpringMVC:用来封装servlet的框架 (struts) Spring:体系整合框架,其他框架的 ...

  5. svn服务器的搭建备份和还原和svnmanager的使用

    svn服务器的搭建备份和还原和svnmanager的使用 一.svn服务端软件的安装和配置 1.安装svn版本库软件 # yum install -y subversion 2.建立svn版本库数据存 ...

  6. T-SQL ORDER BY子句 排序方式

    MS SQL Server ORDER BY子句用于根据一个或多个列以升序或降序对数据进行排序. 默认情况下,一些数据库排序查询结果按升序排列. 语法 以下是ORDER BY子句的基本语法. SELE ...

  7. Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业

    (a) 利用ford-fulkerson算法即可求出最大流和最小分割. (b) 剩余网络为 由S可达的顶点为A.B.可达T的顶点为C. (c) 瓶颈边有e(A,C),e(B,C). (d) 下图中不包 ...

  8. ActiveMQ在Windows下的安装与启动(懒人专属)

    其实这些ActiveMQ官网都有,但是如果你懒得看官网,那就直接看这吧! 1. 官网下载最新的ActiveMQ安装包 apache-activemq-x.x.x-bin.zip并解压   2.进入安装 ...

  9. [正则表达式]匹配Unicode

    一.PHP[PCRE]之Unicode PCRE支持的16进制字符编码转义符有 \x00-\xFF,或\x{num},num为任意位16进制数 但并不支持\u0000-\uFFFF这的形式 PCRE运 ...

  10. python-基于UDP通信的套接字,socketserver模块的使用

    一.基于UDP协议通信的套接字 udp是没有链接的,所以先启动哪一端都不会报错 import socket server=socket.socket(socket.AF_INET,socket.SOC ...