babel-plugin-react-css-modules的配置

前言

題外話。由於‘筆記’不支持上傳圖片,因此只好在‘文章’裏面寫了。。。

以前一直在react項目中使用css-modules。感受使用起來最大的好處就是代碼隔離(scoped),可是同時也產生了很多麻煩。舉個栗子:
不使用css-modulescss

<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-modulesreact

插件效果

若是使用這個插件,跟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

  1. 更方便的使用 css-modules
  2. 支持 scss
  3. 支持全局 scss 變量

開發環境

  1. node // v9.4.0
  2. npm // 6.0.1
  3. create-react-app // 1.5.2
  4. webpack // 3.8.1
  5. react // 16.4.1

以上的版本做爲參考,不一樣的版本能夠會致使後面的配置無效。npm

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')
      }
    }
  ]
},

上圖:
配置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'
        }
      }
    }
  ]
]

上圖:
配置plugin

*重點來了
在配置項中,有generateScopedName這個選項,它的做用和css-loader中的localIdentName是同樣的,都是設置編譯以後的類名的格式。
通過我屢次實驗,generateScopedNamelocalIdentName這兩個配置項必需要有,而且它的值必須相同。不然即便編譯成功,不報錯,也仍是沒法達到預期效果。

filetypes則是讓這個插件支持scss。這裏其實還能夠添加插件,不過尚未實踐。具體能夠在官方文件中查看。

3.全局變量(樣式文件)的支持

其實這個並非必要的,與babel-plugin-react-css-modules這個插件無關。只是在項目中,這個需求基本都會使用到,因此在這裏說起一下。

sass-resources-loader能夠幫助咱們使用全局的scss文件。使用方法也是很簡單的,安裝好插件,而後在剛剛提到的「對 scss 文件的處理」(圖2)配置須要引入的公共文件便可。

最後

以上,關於react的css方案就是這樣了。之後必定會有更好的解決方案,前端的火車‘嗚嗚嗚’,只能不停的開了。

相關文章
相關標籤/搜索