前言
题外话。因为‘笔记’不支持上传图片,所以只好在‘文章’里面写了。。。
之前一直在react项目中使用css-modules
。感觉使用起来最大的好处就是代码隔离(scoped),但是同时也产生了不少麻烦。举个栗子:
不使用css-modules
<div className="the-class">something</div>
使用css-modules
import styles from './styles.css'
<div className={ styles.theTitle }>something</div>
像这样,每次都要用style.xxx
这种方式来写,而且类名要使用小驼峰命名法(习惯css的中杆命名法的我很忧伤),其实还是很麻烦,而它的最大的好处---代码隔离,在不使用css-modules
也可以做到,只是麻烦一点点而已:
// HomePage.js
<div className="home-page-the-class">something</div>
// AccountPage.js
<div className="account-page-the-class">something</div>
// SelectPanel.js
<div className="component-select-panel-the-class">something</div>
所以找了很多新的解决方法,之前还找到了styled-component
这个方案,但是用了之后感觉还是不太合适(谁用谁知道),到目前为止(2018-07-21)找到的比较好的方案是使用babel-plugin-react-css-modules
。
插件效果
如果使用这个插件,跟css-modules
对比一下:
// css-modules
import styles from './styles.css'
<div className={ styles.theTitle }>something</div>
// babel-plugin-react-css-modules
import './styles.css'
<div styleName="the-title">something</div>
而这两种写法达到的效果是一样的。是不是感觉方便很多。
关于插件
官方github链接
在者之前,就有了react-css-modules
这个插件,作者后来又开发了这个使用起来更为方便的新插件,算是很走心了。不过配置起来遇到了很多坑。官方文档中说了很多,但都没有到点子上,相关的配置也不是很详细。
接下来所进行的配置,将达到以下效果:
- 更方便的使用 css-modules
- 支持 scss
- 支持全局 scss 变量
开发环境
- node // v9.4.0
- npm // 6.0.1
- create-react-app // 1.5.2
- webpack // 3.8.1
- react // 16.4.1
以上的版本作为参考,不同的版本可以会导致后面的配置无效。
0.解压webpck配置
npm run eject
1.安装所有依赖的包
// 这里需要注意的是要将此插件安装到 生产模式(--save),而不是开发模式(--save-dev)
npm install babel-plugin-react-css-modules --save
// 该插件让‘babel-plugin-react-css-modules’支持‘scss’
npm install postcss-scss --save-dev
// sass和scss的依赖库
npm install node-sass --save-dev
// sass-loader就不需要说明了吧
npm install sass-loader --save-dev
// 这个插件可以实现全局scss变量,或者说全局的scss文件
npm install sass-resources-loader --save-dev
2.配置
配置部分实在很坑。因为官方提供的配置不是在create-react-app
这个脚手架的基础上进行配置的,所以会有不同。
找到/config/webpack.config.dev.js
。在里面慢慢找(真的是慢慢找),找到:
module.exports.module.rules[ {oneOf} ]
上图:
onOf
是一个数组,在这个数组中的最后添加对scss
文件的处理。添加以下对象:
{
test: /\.scss$/,
use: [
'style-loader',
// 简洁方式
// 'css-loader?modules&localIdentName=[local]-[hash:base64:10]',
{
loader: 'css-loader',
options: {
module: true,
localIdentName: '[local]-[hash:base64:10]'
}
},
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/assets/styles-variable.scss')
}
}
]
},
上图:
这里解释一下css-loader
的配置,options.module
为是否要使用css-modules
;options.localIdentName
为编译之后使用的类名的格式。(其中的‘sass-resources-loader’后面再说)
以上,只是让项目支持了sass
,并开启了css-modules
。接下来,需要配置babel-plugin-react-css-modules
这个插件。
在官方文档中有描述到这个插件的实现原理。它是先将所有的jsx
中的元素的styleName
属性遍历一遍,然后和生成的css
文件进行匹配,生成css-modules
对象,最后将对应的类名添加的元素的className
中。
所以这个过程是在编译.jsx/.js
文件时进行的。
个人见解,不要打我。
在刚刚的onOf
数组中找到对.jsx/.js/.mjs
文件的处理,并添加plugins
:
plugins: [
[
'react-css-modules',
{
generateScopedName: '[local]-[hash:base64:10]',
filetypes: {
'.scss': {
syntax: 'postcss-scss'
}
}
}
]
]
上图:
*重点来了
在配置项中,有generateScopedName
这个选项,它的作用和css-loader
中的localIdentName
是一样的,都是设置编译之后的类名的格式。
经过我多次实验,generateScopedName
和localIdentName
这两个配置项必须要有,并且它的值必须相同。否则即使编译成功,不报错,也还是无法达到预期效果。
而filetypes
则是让这个插件支持scss
。这里其实还可以添加插件,不过还没有实践。具体可以在官方文件中查看。
3.全局变量(样式文件)的支持
其实这个并不是必要的,与babel-plugin-react-css-modules
这个插件无关。只是在项目中,这个需求基本都会使用到,所以在这里提及一下。
sass-resources-loader可以帮助我们使用全局的scss
文件。使用方法也是很简单的,安装好插件,然后在刚刚提到的“对 scss 文件的处理”(图2)配置需要引入的公共文件即可。
最后
以上,关于react
的css方案就是这样了。以后一定会有更好的解决方案,前端的火车‘呜呜呜’,只能不停的开了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。