基于上次的内容 《一步一步做React(一) - Hello React》 ,我们继续搭建一个React项目的工程实践 - CSS Modules。
Github文档 - CSS Modules
CSS Modules里面最基础也是最重要的概念 - 局部作用域。
.backdrop {} .prompt {} .pullquote {}
定义在style.css中的样式都存在于一个组件内的局部作用域,不会污染全局的样式。
import styles from "./style.css" const Component = props => { return ( <div className={styles.backdrop}> <div className={styles.prompt}> </div> <div className={styles.pullquote}> </div> </div> ) }
怎么解释?如何不会污染全局的样式?答案是唯一的命名。现在,我们先来看是怎么配置的。
给webpack.config.js中的module添加一个新的loaders配置,如下:
module: { loaders: [ { test: //.jsx?/, include: APP_DIR, loader: 'babel', }, { test: //.scss$/, loaders: ["style", "css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]", "sass"], }, ], },
webpack的loader是用来预处理由require()或者import加载文件,比如:
import styles from "./style.scss"
在上面的webpack配置中,针对*.scss文件,配置了一个loader的管道,顺序是:
sass-loader => css-loader => style-loader
sass-loader顾名思义用来编译SCSS到CSS
css-loader和style-loader用来将样式嵌入到Webpack打包后的JS文件中,从而实现样式的模块化管理。
针对css-loader的配置,你会看到它的格式是如下的:
css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]
其实,这是webpack loader传递参数的一种方式(URL方式),css-loader的参数表请进入 传送门 。
localIdentName是用于指定局部className的格式,比如:
[name]__[local]___[hash:base64:5] ComponentName__LocalName___HashCode Component__pullquote___SDFe34IIE
正如前面所强调的,style-loader和css-loader,将样式嵌入到Webpack打包后的JS文件。
这当然不是最好的方式,我们需要将样式抽离到独立的css文件中,但就是 Extract Text Plugin 。
yarn add extract-text-webpack-plugin --dev
完整的webpack.config.js文件如下:
const path = require('path'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const BUILD_DIR = path.resolve(__dirname, 'public'); const APP_DIR = path.resolve(__dirname, 'src'); const extractCSS = new ExtractTextPlugin(`${BUILD_DIR}/styles.css`); const config = { entry: `${APP_DIR}/index.jsx`, output: { path: BUILD_DIR, filename: 'bundle.js', }, module: { loaders: [ { test: //.jsx?/, include: APP_DIR, loader: 'babel', }, { test: //.scss$/, loader: extractCSS.extract(['css?minimize&modules&importLoaders=2&localIdentName=[name]__[local]', 'postcss', 'sass']), }, ], }, resolve: { extensions: ['', '.js', '.jsx'], }, plugins: [ extractCSS, ], }; module.exports = config;