在create-react-app
以及eject
之后姨伤,為了使用ant design
熙暴,需要自行配置less-loader
肌幽,根據(jù)antd文檔贪庙,只給出了利用react-app-rewired的解決方案,至于eject
方案团赁,它說(shuō):“不過(guò)這種配置方式需要你自行探索育拨,不在本文討論范圍內(nèi)”。所以本文介紹一下作者的探索結(jié)果然痊。
當(dāng)前關(guān)于這方面的博客非常多,但大都過(guò)時(shí)了屉符,本文是2020年3月31日探索的結(jié)果剧浸。而且發(fā)現(xiàn)一些方案不夠好锹引,他們可能沒(méi)有理解create-react-app
里面getStyleLoaders
的本意。
直接上解決方案唆香,再說(shuō)原因嫌变。
注意:在配置Less-loader之前,我以及先配置了babel-plugin-import
躬它,主要改動(dòng)是在webpack.config.js
添加了這個(gè):
['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent:
'@svgr/webpack?-svgo,+titleProp,+ref![path]',
},
},
},
],
[
'import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: true
},
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
compact: isEnvProduction,
},
},
首先安裝less和less-loader
yarn add less less-loader
然后開(kāi)始處理webpack.config.js
這個(gè)文件
47-53行腾啥,插入了less的兩行:
// style files regexes
const cssRegex =/\.css$/;
const cssModuleRegex =/\.module\.css$/;
const lessRegex =/\.less$/;
const lessModuleRegex =/\.module\.less$/;
const sassRegex =/\.(scss|sass)$/;
const sassModuleRegex =/\.module\.(scss|sass)$/;
72-73行,修改了這個(gè)函數(shù)冯吓,添加了第三個(gè)參數(shù):
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor, preProcessorOptions={}) => {
114-130行倘待,在添加preProcessor
時(shí),補(bǔ)充了options
:
if (preProcessor) {
loaders.push(
{
loader: require.resolve('resolve-url-loader'),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
{
loader: require.resolve(preProcessor),
options: {
sourceMap: true,
...preProcessorOptions,
},
}
);
}
465-493行:
注意:這兩行配置同antd文檔自定義主題配置组贺,可自行修改相關(guān)主題
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader',
{
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
),
sideEffects: true,
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader',
{
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
),
},
說(shuō)幾句原因凸舵。
CRA默認(rèn)配置了sass-loader
,如果配置less-loader
只需要照貓畫虎就可以失尖。但是CRA中寫了一個(gè)getStyleLoaders
函數(shù)啊奄,是為了少些一些重復(fù)性代碼,因?yàn)樘幚?code>.css和.module.css
和.(scss|sass)
和.module.(scss|sass)
中有很多重復(fù)性的配置掀潮。貼出完整的修改前的函數(shù)代碼看看:
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
// css is located in `static/css`, use '../../' to locate index.html folder
// in production `paths.publicUrlOrPath` can be a relative path
options: paths.publicUrlOrPath.startsWith('.')
? { publicPath: '../../' }
: {},
},
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
{
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
// Adds PostCSS Normalize as the reset css with default options,
// so that it honors browserslist config in package.json
// which in turn let's users customize the target behavior as per their needs.
postcssNormalize(),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push(
{
loader: require.resolve('resolve-url-loader'),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
{
loader: require.resolve(preProcessor),
options: {
sourceMap: true,
},
}
);
}
return loaders;
};
其實(shí)對(duì)preProcessor的處理關(guān)鍵就在于最后幾行
{
loader: require.resolve(preProcessor),
options: {
sourceMap: true,
},
}
遺憾的是菇夸,它把options
寫死了,但是為了靈活定制options
仪吧,但是又不打破CRA設(shè)計(jì)這個(gè)函數(shù)的初衷庄新,必須加個(gè)參數(shù)來(lái)表明options
。
最后想補(bǔ)充一點(diǎn)邑商,如果項(xiàng)目中不會(huì)用到.module.less
摄咆,可以把這幾行注釋掉or刪掉(其實(shí)ant design
中好像沒(méi)用到.module.less
,都是.less
)人断。不然每次修改主題都需要改兩個(gè)地方吭从,比較麻煩(或者提取這個(gè)options
或modifyVars
成一個(gè)常量放在文件開(kāi)頭常量定義的地方也可以)。
// const lessModuleRegex =/\.module\.less$/;
{
test: lessRegex,
// exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader',
{
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
),
sideEffects: true,
},
/*{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader',
{
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
),
},*/