創(chuàng)建日期: 2020年3月2日
Demo源碼下載
參考鏈接:
鏈接1
鏈接2
customize-cra API
前言:
如果你想通過不暴露webpack,配置less,并且只想知道步驟,不關(guān)心你配置時候為什么不好用理卑,可以直接劃到下面看【3.總結(jié)】。
如果,你是初學(xué)者小白扇单,并沒有項目,你需要做如下準(zhǔn)備工作:
用create-react-app (CRA)腳手架或者IDE創(chuàng)建React項目奠旺。
參考:React入門(1)——我的第一個React.js項目
1.安裝less和less-loader
//npm
$ npm install --save-dev less-loader less
//yarn
$ yarn add less less-loader -D
遺留問題:為什么我按官網(wǎng)的命令去安裝less蜘澜,在package.json里面不會顯示,而用上面的方式响疚,就會顯示呢鄙信?需要查下npm的子命令了。
[參考]
安裝后忿晕,我們會看到package.json文件中装诡,添加了依賴:
"devDependencies": {
"less": "^3.11.1",
"less-loader": "^5.0.0"
}
Dependencies和devDependencies到底有什么區(qū)別呢?
[參考鏈接]
2. 配置
2.1 方法一:暴露webpack
哇靶硬凇慎王!好尷尬??,翻了半天宏侍,也沒找到網(wǎng)上說的webpack.config.js文件赖淤,原因看這個。
下面這個命令谅河,謹(jǐn)慎執(zhí)行咱旱,因為不可逆。
但是只要做好代碼版本管理绷耍,可以隨意折騰吐限,大不了重頭再來版本管理git的使用
2.1.1 yarn eject
$ yarn eject
執(zhí)行的時候,有提示:NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html
因為褂始,執(zhí)行該命令后會把已構(gòu)建依賴項诸典、配置文件和腳本復(fù)制到程序目錄中。該操作是不可逆轉(zhuǎn)的崎苗,執(zhí)行完成后會刪除這個命令狐粱,也就是說只能執(zhí)行一次舀寓。
插曲:執(zhí)行的時候,被git給阻擋了肌蜻,因為是在學(xué)習(xí)互墓,所以我直接用
$ find . -name ".git" | xargs rm -Rf
用這個命令把git給清除了。如果是項目蒋搜,自己按照提示篡撵,把git相關(guān)的commit,stash什么的豆挽,處理完畢就好育谬。
執(zhí)行完畢后,package.json文件被更改了祷杈,與此同時斑司,會生成新文件夾config:
2.1.2修改webpack.config.js配置文件。
我們找到sassRegex但汞,模仿它來配置lessRegex宿刮。
(1).配置less
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/; //這一句和下一句是新增的less的配置
const lessModuleRegex = /\.module\.less$/;
(2).配置less-loader
找到"test: sassRegex"這個,搜一下即可私蕾,然后模仿這個來寫less的僵缺。
// Adds support for CSS Modules, but using LESS
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
modules: true,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader'
),
sideEffects: true,
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader'
),
},
這里,我先直接copy了sass的配置踩叭,然后改成less磕潮,運(yùn)行后不好用。之后容贝,又在lessRegex里加了一句modules: true,才可以運(yùn)行自脯。致于 importLoaders: 3,這后面的數(shù)字斤富,是3膏潮,是1,都好用满力,沒有查具體意義焕参。待調(diào)查
2.1.3 修改代碼
新建styles.less文件:
//styles.less
.title {
color: red;
}
修改index.js文件:
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.less'
const App = () => {
console.log(styles);//打印一下,是一個對象油额,對象的元素的key是title
return(
<h1 className={styles.title}>Hello world</h1>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
這里叠纷,引入less文件,作為styles潦嘶,設(shè)置className的時候涩嚣,將原本的雙引號,改成花括號。至此缓艳,less的引用成功校摩。
參考鏈接1:樣式設(shè)置和CSS文件引入
配置的時候請注意:關(guān)于 less 配置規(guī)則放在 sass 的解析規(guī)則下面即可看峻,如果放在了 file-loader 的解析規(guī)則下面阶淘,less 文件解析不會生效。(這段注意來自于網(wǎng)絡(luò)互妓,沒有驗證過)
2.2 配置方法二:無需eject進(jìn)行配置(不用暴露webpack)
參考1: Create React App無eject配置(react-app-rewired 和 customize-cra)
參考2: create-react-app 優(yōu)雅定制指南
初學(xué)者:因為溪窒,eject是一個不可逆的過程,所以冯勉,這里澈蚌,你需要重新創(chuàng)建一個項目來實驗。新建項目后灼狰,參照上面宛瞄,修改代碼,新建styles.less文件交胚,以及修改inde.js文件份汗。記得要安裝less和less-loader。然后蝴簇,運(yùn)行杯活。嗯,hello world是黑色的熬词,styles.less的文件沒有被成功調(diào)用旁钧。
下面,我們來進(jìn)行第二種互拾,相對優(yōu)雅的設(shè)置方案歪今。
react-app-rewired
是 react 社區(qū)開源的一個修改 CRA 配置的工具。純 react-app-rewired 的方式自定義配置颜矿,參考 Extended Configuration Options 文檔寄猩。
注意
react-app-rewired 1.x 配合 create-react-app 1.x
react-app-rewired 2.x 配合 create-react-app 2.x
版本升級導(dǎo)致互不兼容,另外或衡,react-app-rewired 2.x 應(yīng)該是社區(qū)維護(hù)了焦影。
react-app-rewired@^2.0.0+ 版本需要搭配 customize-cra 使用
在 react-app-rewired 1.x 的版本中,它除了提供覆蓋配置的方法封断,還體用了一些 helpers斯辰,例如 rewireLess、rewirePreact 等坡疼,2.x 版本只保留了核心功能彬呻。
另外一個工具幫我們實現(xiàn)了這些,customize-cra.
customize-cra
這次我們使用 customize-cra 協(xié)助自定義,參考 Using the plugins 文檔闸氮。
2.2.1 安裝
yarn add react-app-rewired customize-cra -D
2.2.2 修改package.json文件
//package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
},
2.2.3 在項目根目錄新建config-overrides.js
//config-overrides.js
const { override } = require('customize-cra');
module.exports = {};
2.2.4 配置less (在react使用JavaScript語言下)
在第一部分中剪况,我們已經(jīng)安裝了less和less-loader依賴,這里我們開始配置蒲跨。
這個過程中译断,筆者找了很多文章來看,大部分都是依賴react-app-rewired來做的或悲,但是孙咪,文章比較老,現(xiàn)在版本更新巡语,我們需要[customize-cra]來協(xié)助翎蹈。
customize-cra API docs
addLessLoader(loaderOptions)
我們來修改config-overrides.js文件:
//config-overrides.js
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
}),
)
好了,less配置成功男公,來運(yùn)行你的代碼吧荤堪!
??????,什么?枢赔?澄阳?不好用?糠爬?寇荧?
沒錯,確實不好用!筆者也在這里卡住了执隧,讀了數(shù)十篇文章揩抡,依然沒有找到解決方案,最終镀琉,還是回歸官網(wǎng)的文檔峦嗤,才搞明白緣由。
其實屋摔,CRA生成的React項目烁设,是可以直接用css modules的,但是钓试,css文件的命名是有規(guī)則的装黑,例如:styles.module.css。同理依賴css modules的less弓熏,文件名的命名規(guī)則也如此:styles.module.less恋谭。
好了,我們修改下文件名及index.js里的引用挽鞠,再運(yùn)行一次代碼疚颊。
報錯:
至此狈孔,我已哭死!!!調(diào)查后,發(fā)現(xiàn)是因為css-loader更新到3.0以后材义,出現(xiàn)的這個問題均抽,也因此,之前博客的方法其掂,都不起作用油挥。
參考1: https://github.com/arackaf/customize-cra/issues/201
我們先將"customize-cra": "^1.0.0-alpha.0"升級,此時清寇,用的就是這個版本的喘漏,
然后參考:https://github.com/rails/webpacker/issues/2197的gyurcigyurma說的,將config-overrides.js文件改成如下:(此時华烟,使用的是styles.module.less文件名)
//config-overrides.js
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: true
}
}),
)
好了,我看到紅色的Hello world了持灰,終于可以正確運(yùn)行了盔夜。。堤魁。
2.2.5 配置less(在react使用TypeScript語言下)
用IDE新建項目喂链,比如webStorm,新建時妥泉,選擇支持TypeScript椭微。參考上面的1~4,進(jìn)行一次盲链,less文件用styles.modules.less這種.modules.less命名規(guī)則蝇率。我們也要更新customize-cra
的版本。
除此之外刽沾,還有修改react-app-env.d.ts文件:
//react-app-env.d.ts
declare module "*.module.less"
筆者第二次執(zhí)行時本慕,運(yùn)行一直出錯,提示:
./src/styles.module.less (./node_modules/css-loader/dist/cjs.js??ref--6-oneOf-8-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--6-oneOf-8-3!./node_modules/less-loader/dist/cjs.js??ref--6-oneOf-8-4!./src/styles.module.less)
ValidationError: Invalid options object. Less Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'options'. These properties are valid:
object { lessOptions?, prependData?, appendData?, sourceMap? }
筆者修改了config-overrides.js:
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
}),
)
好了侧漓,運(yùn)行成功锅尘,我們看見了紅色Hellow world。
因為沒有第一次運(yùn)行時候的demo布蔗,所以藤违,筆者并不確定問題具體出在哪,即便纵揍,按上面的步驟走顿乒,估計也會出錯,因為less-loader更新了骡男。淆游。傍睹。
為此,筆者貼出自己實驗的時候犹菱,所用依賴包的信息拾稳,僅供參考。
"devDependencies": {
"customize-cra": "^1.0.0-alpha.0",
"less": "^3.11.1",
"less-loader": "^5.0.0",
"react-app-rewired": "^2.1.5"
}
2.2.6 配置less(在react使用TypeScript語言下的優(yōu)化–––去掉含module的后綴名)
修改config-overrides.js:
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
javascriptEnabled: true,
cssLoaderOptions: {
modules: {localIdentName: '[name]_[local]_[hash:base64:5]'},
}, // .less file used css-loader option, not all CSS file.
}),
)
修改react-app-env.d.ts文件:
/// <reference types="react-scripts" />
declare module "*.less"
最后腊脱,注意也要修改styles.less的文件名以及在indext.tsx的import路徑访得。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2.6 擴(kuò)展:引用CSS Module
新建文件styles.module.css
//styles.module.css
.title {
color: blue;
}
修改index.js文件:
//index.js
import stylesCss from './styles.module.css'
//.......省略
<h1 className={stylesCss.title}>Hello CSS Modules</h1>
//.......省略
運(yùn)行,成功陕凹。
3. 總結(jié)
為了方便快速瀏覽悍抑,筆者對第二種比較優(yōu)雅的配置方法,進(jìn)行總結(jié)杜耙。如果上面部分已經(jīng)看過了搜骡,這部分可以忽略,僅僅是對上面陳述的方法二的總結(jié)佑女。
3.1 安裝依賴
#安裝less和less-loader
$yarn add less less-loader -D
#安裝react-app-rewired
$yarn add react-app-rewired -D
#安裝customize-cra 如果记靡,你安裝時的最新版本已經(jīng)超過這個,可以不用指定版本
$yarn add customize-cra@^1.0.0-alpha.0 -D
3.2 修改package.json文件
//package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
},
3.3 在項目根目錄新建config-overrides.js
并對less進(jìn)行配置:
//config-overrides.js
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: true
}
}),
)
3.4 對于支持TypeScript的項目的配置
修改config-overrides.js:
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
}),
)
修改react-app-env.d.ts文件:
//react-app-env.d.ts
declare module "*.module.less"
3.5 對于支持TypeScript的項目的配置的優(yōu)化(去掉.module的后綴)
修改config-overrides.js:
const { override, addLessLoader } = require('customize-cra');
module.exports = override(
addLessLoader({
strictMath: true,
noIeCompat: true,
javascriptEnabled: true,
cssLoaderOptions: {
modules: {localIdentName: '[name]_[local]_[hash:base64:5]'},
}, // .less file used css-loader option, not all CSS file.
}),
)
修改react-app-env.d.ts文件:
/// <reference types="react-scripts" />
declare module "*.less"
最后团驱,注意也要修改styles.less的文件名以及在indext.tsx的import路徑摸吠。
3.6 測試
注意less文件命名規(guī)則,后綴為.module.less
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.module.less'
const App = () => {
console.log(styles);//打印一下嚎花,是一個對象寸痢,對象的元素的key是title
return(
<h1 className={styles.title}>Hello world</h1>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
//styles.module.less
.title {
color: red;
}
3.7 糾錯
筆者,在第二次補(bǔ)充的時候紊选,發(fā)現(xiàn)又跑不起來了啼止。經(jīng)調(diào)查,發(fā)現(xiàn)是因為less-loader版本更新的原因丛楚,為此族壳,筆者貼出測試的時候,所用依賴庫的版本:
"devDependencies": {
"customize-cra": "^1.0.0-alpha.0",
"less": "^3.11.1",
"less-loader": "^5.0.0",
"react-app-rewired": "^2.1.5"
}
網(wǎng)上趣些,查看各種文檔都不好用的時候仿荆,包括筆者這篇也被淘汰的時候,建議你看看官網(wǎng)customize-cra API坏平,這個是找答案最快捷的辦法拢操。