題外話。由於‘筆記’不支持上傳圖片,因此只好在‘文章’裏面寫了。。。
以前一直在react項目中使用css-modules
。感受使用起來最大的好處就是代碼隔離(scoped),可是同時也產生了很多麻煩。舉個栗子:
不使用css-modules
css
<div className="the-class">something</div>
使用css-modules
前端
import styles from './styles.css' <div className={ styles.theTitle }>something</div>
像這樣,每次都要用style.xxx
這種方式來寫,並且類名要使用小駝峯命名法(習慣css的中杆命名法的我很憂傷),其實仍是很麻煩,而它的最大的好處---代碼隔離,在不使用css-modules
也能夠作到,只是麻煩一點點而已:node
// 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
。react
若是使用這個插件,跟css-modules
對比一下:webpack
// 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>
而這兩種寫法達到的效果是同樣的。是否是感受方便不少。git
官方github連接
在者以前,就有了react-css-modules
這個插件,做者後來又開發了這個使用起來更爲方便的新插件,算是很走心了。不過配置起來遇到了不少坑。官方文檔中說了不少,但都沒有到點子上,相關的配置也不是很詳細。github
接下來所進行的配置,將達到如下效果:web
以上的版本做爲參考,不一樣的版本能夠會致使後面的配置無效。npm
npm run eject
// 這裏須要注意的是要將此插件安裝到 生產模式(--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
配置部分實在很坑。由於官方提供的配置不是在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
。這裏其實還能夠添加插件,不過尚未實踐。具體能夠在官方文件中查看。
其實這個並非必要的,與babel-plugin-react-css-modules
這個插件無關。只是在項目中,這個需求基本都會使用到,因此在這裏說起一下。
sass-resources-loader能夠幫助咱們使用全局的scss
文件。使用方法也是很簡單的,安裝好插件,而後在剛剛提到的「對 scss 文件的處理」(圖2)配置須要引入的公共文件便可。
以上,關於react
的css方案就是這樣了。之後必定會有更好的解決方案,前端的火車‘嗚嗚嗚’,只能不停的開了。