这两天正在学习react,学习使用ant-desgin快速搭建网站,在配置按需引入和自定义主题的时候,遇到一些问题,特此记录一下整个配置流程和解决方案的过程。如果仅仅是想看如何配置的伙伴,请移步至第五节总结部分。
注:本次配置好的项目可以查看GitHub地址,寻找源码。
我们先使用create-react-app
创建一个react项目,方便后面的ant-design
的引入和基本样式的搭建,这里直接创建一个小demo。
create-react-app demo
如果你的电脑没有安装create-react-app
的话,请使用如下命令进行安装:
npm install create-react-app -g
项目搭建:
项目搭建完毕之后我们使用vscode打开项目,并使用npm start
或者是yarn start
启动项目。
当然,我们在后续的使用时,并不需要这些东西,所以要把src
目录下面的index.js
留下,其他的全部删掉,并新建一个App.jsx
,
index.js
如下
import React from "react"
import ReactDOM from "react-dom/client"
import App from './App'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<App/>
)
App.jsx
如下:
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>App</div>
)
}
}
接下来就是安装ant-design
到这个小demo中,点击这里前往ant-desgin
的官网。
我们使用yarn
命令安装:
yarn add antd
这里将介绍antd
的基本使用,只要学会了一个组件的使用,其他组件的使用方式也是大同小异,由于只是简单的演示,所以一切样式都在App
组件里面实现。
选用最基础的一种样式,点开下面的显示代码:
从antd
中引入Button
组件:
import { Button } from 'antd';
在render
区域使用此组件:
最终App
组件里面的代码如下:
import React, { Component } from 'react'
import { Button } from 'antd'
export default class App extends Component {
render() {
return (
<div>
App... <br />
<Button type="primary">Primary Button</Button>
</div>
)
}
}
antd
的图标是语义化的矢量图形。使用图标组件,需要先安装 @ant-design/icons
图标组件包:
yarn add @ant-design/icons
选择一组想要展示的图标,点击这个图标,会自动复制这个图标组件的标签,将其粘贴到需要展示图标的组件中。
render() {
return (
<div>
....
<DingtalkOutlined />
<WechatOutlined />
</div>
)
}
但是这样是还不能显示图标的,需要引入刚才安装的图标组件包。
引入所需图标:
import { DingtalkOutlined, WechatOutlined } from '@ant-design/icons'
保存重新编译之后,这两个图标就能在页面上正常显示了。
现在App
组件里面的代码如下:
import React, { Component } from 'react'
import { Button } from 'antd'
import { DingtalkOutlined, WechatOutlined } from '@ant-design/icons'
export default class App extends Component {
render() {
return (
<div>
App... <br />
<Button type="primary">Primary Button</Button>
<br />
<DingtalkOutlined />
<WechatOutlined />
</div>
)
}
}
我们可以看到,Button
组件里面使用了type
API,定义其类型为primary
,这个按钮的颜色应该是主题蓝色才对,但是页面中的按钮,却是没有颜色的:
打开node_modules
文件夹下antd/dist
,可以看到有一个antd.css
的文件,里面存放了antd
的所有样式。
antd
从4.x开始,就将组件和样式等文件都分开了,刚才在引入Button
组件的时候是从antd.js
中引入,并没有引入antd.css
,所以这里需要引入一下这个css文件,才能正常显示样式。
import 'antd/dist/antd.css'
样式完成显示了,但是不要着急,切换到控制台看一下输出:
一堆警告……
根据这些警告,我找到了antd
的issues,找到如下解决办法。
(1) 将antd.css
修改成antd.min.css
再引入:
import 'antd/dist/antd.min.css'
查看结果,控制台无报错:
浏览器里面的样式也是没有问题的,这个方法可行。
(2) 新建一个App.css
,在里面使用@import
引入样式,然后再将App.css
引入到App
组件中
删掉上一个方法的引入,在App.css
中的引入如下:
@import '~antd/dist/antd.css'
在App
组件中的引入如下:
import './App.css'
保存编译之后,控制台没有报错:
浏览器中样式显示正常:
至此,antd
的基本使用已经讲解完毕,后续在使用其他组件也是差不多的方法,可以查看每个组件的API
,给组件添加事件、样式、属性等。
在上面的样式引入中,我们直接引入了整个antd.css
文件,加载了所有antd
组件的样式(gzipped 后一共大约 60kb)。
我们直接用SpaceSniffer看一下全部引入css样式后打包的的体积,可以看到css样式表文件占据一大部分。
打包时间比较长,有251.47s
整个文件的打包体积也达到了2.7MB之多。
跟着我引入antd组件的小伙伴都知道,在上面的代码编写中,我们只放了一个Button
按钮组件(icon图标是来源于@ant-design/icons
图标组件包),很显然我们引入了很多无用的组件样式。这个时候,如果react能根据我们所写的组件,导入对应组件所需的样式,这样在项目打包的时候,就能节省一大部分空间。
ant-design官方提供了按需引入的方式,在高级配置中可以看到具体的配置方式,这里我将具体的配置做了如下总结。
此时我们需要对 create-react-app
的默认配置进行自定义,这里我们使用 react-app-rewired (一个对 create-react-app 进行自定义配置的社区解决方案)。
引入 react-app-rewired 并修改 package.json 里的启动配置。由于新的 [email protected] 版本的关系,你还需要安装 customize-cra。
yarn add react-app-rewired customize-cra
修改package.json
的scripts节点,更改默认的执行脚本。
/* package.json */
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
在项目的根目录下面新建一个config-overrides.js
文件,在里面添加如下配置代码,用于默认配置。
module.exports = function override(config, env) {
// do stuff with the webpack config...
return config;
};
此时我们还没有进行任何配置,所以说配置还不能生效。
我们需要安装一个能够按需加载组件代码和样式的插件babel-plugin-import
babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件(原理)。
yarn add babel-plugin-import
将config-overrides.js
中的配置替换成下面的配置选项。
const { override, fixBabelImports } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
);
移除App.css
中使用@import
引入css文件的代码,重新启动项目。
我们将配置好的项目打包,看看打包后的结果。
这里我为了方便做对比,新建了一个demo-1的小demo,除了按需引入部分配置,内容和插件安装方式等都是和刚开始的demo是一样的。
我们在使用antd的时候不难发现,不管是按钮的默认颜色还好,还是时间选择组件,还是input输入框的focus边框颜色,都是基于支付宝蓝作为主题色进行设计的。但是在项目开发中,也有其他的主题颜色的需求。
常见的修改方式就是,找到设置组件为蓝色那个class选择器,在里面写上需要的颜色,然后加上权重。这种方式进行样式修改也是可行的,但是在设计antd的时候,设计者可能也添加了权重,导致我们自己定义的颜色不一定能显示。而且如果需要修改多个组件的主题色的话,多次定义就显得比较麻烦。
对于以上情况,antd官网也提供了想要的配置方法,但是我在自己配置的时候,踩了不少坑,现在就一一进行配置,并填补这些坑。
antd在设计的时候,使用less进行组件样式的设定。官方文档提到需要使用less变量覆盖功能,替换成我们需要的主题。引入 customize-cra
中提供的 less 相关的函数 addLessLoader 来帮助加载 less 样式,同时修改 config-overrides.js
文件。
首先安装less和less-loader
yarn add less less-loader
找到config-overrides.js
文件,把fixBabelImports
函数下面的style
的值由'css'
改为true
。
然后再这个函数的后面添加以下代码:
addLessLoader({
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' }, // #以及后面的就是你需要切换的主题色,更改这个颜色代码就可以更改主题色了
}),
这里利用了 less-loader 的 modifyVars
来进行主题配置。
yarn start
重启项目:
有报错,说是我们配置的对象是无效的,且在配置中modifyVars
是未知的,
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 'modifyVars'. These properties are valid:
object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }
at validate
查看customize-cra
的issues找到,我们所添加到addLessLoader
里面的配置由于less-loader的更新,新版本的写法发生了变化,原来addLessLoader
的配置选项现在需要嵌套到一个lessOptions
对象中去。
新版本的写法应该是这样的:
// config-overrides.js
const { override, fixBabelImports, addLessLoader } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
lessOptions: {
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
}),
);
还是有报错(捂脸),但是这个报错和之前不一样了,这个问题是由于使用了create-react-app
的问题,因为版本升级到了5.0.1,所以webpack的版本也变成了5.0.1,
我们可以在config-overrides.js
文件中addLessLoader
后面添加如下代码:
adjustStyleLoaders(({ use: [, , postcss] }) => {
const postcssOptions = postcss.options;
postcss.options = { postcssOptions };
})
别忘了在前面require引入的时候,添加adjustStyleLoaders
的引入。
最终config-overrides.js
的配置代码如下:
const { override, fixBabelImports, addLessLoader, adjustStyleLoaders } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
lessOptions: {
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
}),
adjustStyleLoaders(({ use: [, , postcss] }) => {
const postcssOptions = postcss.options;
postcss.options = { postcssOptions };
})
);
然后重启项目即可。
浏览器页面已经修改成所需颜色:
我们在配置的时候,肯定不可能只是定义全局主色这么简单,还可能需要配置其他的颜色、字号、圆角大小等,可以参考选下面的通用变量,所有的样式变量点击这里可以查看。
@primary-color: #1890ff; // 全局主色
@link-color: #1890ff; // 链接色
@success-color: #52c41a; // 成功色
@warning-color: #faad14; // 警告色
@error-color: #f5222d; // 错误色
@font-size-base: 14px; // 主字号
@heading-color: rgba(0, 0, 0, 0.85); // 标题色
@text-color: rgba(0, 0, 0, 0.65); // 主文本色
@text-color-secondary : rgba(0, 0, 0, .45); // 次文本色
@disabled-color : rgba(0, 0, 0, .25); // 失效色
@border-radius-base: 4px; // 组件/浮层圆角
@border-color-base: #d9d9d9; // 边框色
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // 浮层阴影
这里就写上一步到位的配置吧,不用弯弯绕绕了,有需求的小伙伴直接安装配置就行。
安装ant-design
:
## yarn
yarn add antd
## npm
npm install antd
安装@ant-design/icons
图标组件包:
## yarn
yarn add @ant-design/icons
## npm
npm install @ant-design/icons
按需引入插件安装:
## yarn
yarn add react-app-rewired customize-cra babel-plugin-import
## npm
npm install react-app-rewired customize-cra babel-plugin-import
自定义主题安装less 和 less-loader
## yarn
yarn add less less-loader
## npm
npm install less less-loader
修改package.json
中scripts节点:
/* package.json */
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
在项目根目录新建一个名为config-overrides.js
的文件
按需引入组件和组件css样式表配置代码:
const { override, fixBabelImports } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
);
按需引入+自定义主题配置代码:
const { override, fixBabelImports, addLessLoader, adjustStyleLoaders } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
lessOptions: {
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
}),
adjustStyleLoaders(({ use: [, , postcss] }) => {
const postcssOptions = postcss.options;
postcss.options = { postcssOptions };
})
);
按需引入+自定义主题配置代码:
const { override, fixBabelImports, addLessLoader, adjustStyleLoaders } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
lessOptions: {
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}
}),
adjustStyleLoaders(({ use: [, , postcss] }) => {
const postcssOptions = postcss.options;
postcss.options = { postcssOptions };
})
);
有什么问题请指正!