1、前导信息
众所周知,使用create-react-app(官方文档)构建项目时,会把webpack相关配置都隐藏起来了,若需要修改配置可以执行以下命令将配置文件弹出来,但此操作是不可逆的
npm run eject
需要注意的是,执行 eject
后,你将不再享受 Create React App 提供的抽象和自动化功能,同时也需要自行处理配置和构建的相关问题。这意味着你对项目的配置和构建有更多的责任和掌控,但也能满足更灵活的定制需求。
为了在不eject的情况下自定义某些配置,使用craco(Create React App Configuration Override)插件就是其中一个比较常用的方案
2、配置详情(craco文档craco.js.org/docs/)
在安装@craco/craco之前我们先观察node_modules文件夹,可以发现有些我们所需要的包已经安装
这是因为执行 npm init react-app my-app 时自动安装了react-scripts插件,它为了我们集成了webpack\babel\postcss\lodash 等一系列常用的工具和配置,所以再自定义其他相关配置时我们可以安装需要的即可
2.1、安装@craco/craco
npm i @craco/craco -D
2.2、在项目根目录创建一个craco.config.js文件
2.2.1、配置less预处理器(项目中可以使用less文件及语法)
只需安装craco-less即可,查询craco-less的package.json可以发现项目中已经依赖了less,less-loader插件,所有我们只需安装craco-less即可
npm i craco-less -D
// craco.config.js文件
const CracoLessPlugin = require('craco-less')
module.exports = {
//...
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: { // 配置可以参照webpack的less-loader具体配置
lessOptions: {
javascriptEnabled: true // 允许less文件中使用js表达式
}
}
}
}
],
//...
}
2.2.2、配置移动端自适应postcss-pxtorem
项目初始化时已经安装了postcss postcss-loader,所以此处不需要在安装
npm i lib-flexible postcss-pxtorem -D
- 入口文件index.tsx中引入lib-flexible
- 配置postcss-pxtorem
// craco.config.js文件
const postcssPx2Rem = require('postcss-pxtorem')
module.exports = {
//...
style: {
postcss: {
mode: 'extends',
loaderOptions: () => {
return {
postcssOptions: {
ident: 'postcss',
config: false,
plugins: [
postcssPx2Rem({
rootValue: 37.5, // 设计稿尺寸/10
propList: ['*'], // 需要转换的样式属性,默认为 ['*'],即匹配所有属性
exclude: /node_modules/i // 排除掉node_modules中转换
})
]
},
sourceMap: false
}
}
}
},
//...
}
2.2.3、配置devserver(代理相关)
// craco.config.js文件
module.exports = {
//...
devServer: {
port: 8888,
hot: true,
client: {
overlay: false
},
// 配置代理解决跨域
proxy: {
'/': {
target: process.env.REACT_APP_URL, // https://xxx.com
changeOrigin: true,
pathRewrite: {
'^/': ''
}
}
}
}
//...
}
2.2.3、配置webpack相关(别名及打包大小分析)
// craco.config.js文件
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
module.exports = {
// ...
webpack: {
// 配置别名
alias: {
// 约定:使用 @ 表示 src 文件所在路径
'@': path.resolve(__dirname, 'src')
},
plugins: [
// 打包分析插件,需要分析时解开注释
// [new BundleAnalyzerPlugin()]
],
// ...
}
- 包大小分析结果
2.2.3、配置webpack相关(拆包、打包路径等)
// craco.config.js文件
module.exports = {
// ...
webpack: {
configure: webpackConfig => {
// 生产环境配置
if (isProd) {
// 去除map文件
webpackConfig.devtool = false
// 拆包
webpackConfig.optimization = {
splitChunks: {
chunks: 'async',
minSize: 40000, // bite
maxAsyncRequests: 10, // 最大异步请求数
maxInitialRequests: 10, // 页面初始化最大异步请求数
automaticNameDelimiter: '~', // 解决命名冲突
name: false,
cacheGroups: {
antd: {
name: 'chunk-antd',
chunks: 'all',
test: /[\\/]node_modules[\\/](@ant-design|antd-mobile)[\\/]/,
priority: -7
},
common: {
name: 'chunk-common',
chunks: 'all',
test: /[\\/]node_modules[\\/](react|react-dom|react-router|react-redux|react-router-dom|redux-persist|react-fastclick)[\\/]/,
priority: -9
},
vendor: {
name: 'chunk-vendor',
chunks: 'all',
test: /[\\/]node_modules[\\/](axios|lodash|core-js|react-copy-to-clipboard|crypto-js|web-vitals)[\\/]/,
priority: -10
}
}
}
}
// 输出output
webpackConfig.output = {
...webpackConfig.output,
publicPath: './' // 打包资源引入路径--目前使用的是相对路径
}
}
return webpackConfig
}
},
// ...
}
- 拆包结果
- 打包资源引入路径
2.2.4、配置生产环境打包后删除console
module.exports = {
babel: {
plugins: [
// 生产环境只留console.error、warn,去除console.log
[
'babel-plugin-transform-remove-console',
{ exclude: isProd ? ['error', 'warn'] : ['error', 'warn', 'log'] }
]
]
},
}
2.3、修改package.json文件的运行命令
"scripts": {
"start": "craco start" // react-scripts start --> craco start
"build": "craco build" // react-scripts build --> craco build
}
2.3.1、使用dotenv-cli加载开发、测试、生产不同环境的环境变量
npm i dotenv-cli -D
package.json 文件的配置
{
"scripts": {
"dev": "craco start",
"prod": "dotenv -e .env.production craco start",
"build:dev": "dotenv -e .env.development craco build",
"build:test": "dotenv -e .env.test craco build",
"build:prod": "dotenv -e .env.production craco build",
"eject": "react-scripts eject",
"lint": "eslint -c .eslintrc.js src --ext .ts,.tsx,.js,.jsx --fix",
"clean": "rimraf node_modules"
},
}
- craco.config.js 的全部配置(拆包模块为本项目所使用的一些包,可自行修改)
/* eslint-disable @typescript-eslint/no-var-requires */
//对webpack配置别名
const path = require('path')
require('react-scripts/config/env')
const url = process.env.REACT_APP_URL
// 移动端rem适配
const CracoLessPlugin = require('craco-less')
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const isProd = process.env.NODE_ENV === 'production'
const postcssPx2Rem = require('postcss-pxtorem')
module.exports = {
// webpack 配置
webpack: {
// 配置别名
alias: {
// 约定:使用 @ 表示 src 文件所在路径
'@': path.resolve(__dirname, 'src')
},
plugins: [
// 打包分析插件,需要分析时解开注释
// [new BundleAnalyzerPlugin()]
],
configure: webpackConfig => {
// 生产环境配置
if (isProd) {
// 去除map文件
webpackConfig.devtool = false
// 拆包
webpackConfig.optimization = {
splitChunks: {
chunks: 'async',
minSize: 40000, // bite
maxAsyncRequests: 10, // 最大异步请求数
maxInitialRequests: 10, // 页面初始化最大异步请求数
automaticNameDelimiter: '~', // 解决命名冲突
name: false,
cacheGroups: {
antd: {
name: 'chunk-antd',
chunks: 'all',
test: /[\\/]node_modules[\\/](@ant-design|antd-mobile)[\\/]/,
priority: -7
},
common: {
name: 'chunk-common',
chunks: 'all',
test: /[\\/]node_modules[\\/](react|react-dom|react-router|react-redux|react-router-dom|redux-persist|react-fastclick)[\\/]/,
priority: -9
},
vendor: {
name: 'chunk-vendor',
chunks: 'all',
test: /[\\/]node_modules[\\/](axios|lodash|core-js|react-copy-to-clipboard|crypto-js|web-vitals)[\\/]/,
priority: -10
}
}
}
}
// 输出
webpackConfig.output = {
...webpackConfig.output,
publicPath: './'
}
}
return webpackConfig
}
},
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
javascriptEnabled: true // 允许less文件中使用js表达式
}
}
}
}
],
style: {
postcss: {
mode: 'extends',
loaderOptions: () => {
return {
postcssOptions: {
ident: 'postcss',
config: false,
plugins: [
postcssPx2Rem({
rootValue: 37.5, // 设计稿尺寸/10
propList: ['*'], // 需要转换的属性,默认为 ['*']
exclude: /node_modules/i // 哪些文件不需要转换
})
]
},
sourceMap: false
}
}
}
},
babel: {
plugins: [
// 生产环境只留console.error、warn,去除console.log
[
'babel-plugin-transform-remove-console',
{ exclude: isProd ? ['error', 'warn'] : ['error', 'warn', 'log'] }
]
]
},
devServer: {
port: 8888,
// open: true,
hot: true,
client: {
overlay: false
},
// 配置代理解决跨域
proxy: {
'/': {
target: url,
changeOrigin: true,
pathRewrite: {
'^/': ''
}
}
}
}
}
以上就是今天的全部内容了,如有错误,欢迎指正!