React踩坑--配置篇

本文最后更新于:2020年12月17日 凌晨

最近在使用React的脚手架create-react-app搭建项目的时候踩了一些坑,主要都是配置方面的坑,大体上是因为React官方是把webpack等配置都封装好并隐藏起来,所以如果需要自定义配置需要自行处理,当然脚手架也提供了eject命令来释放配置,但是这是一个单向不可逆操作,释放了就回不来了,所以最好不要随便就释放配置。

但是我在踩坑的过程中搜索资料发现,很多人分享的经验,都是基于释放配置的情况。这种操作我个人不是很喜欢,脚手架将配置封装好隐藏起来肯定有它的道理,至少优化方面肯定是做足的,如果如果能通过其它方法来解决,自然是能不释放配置为好,这也是我做本篇记录的一个原因,以下是我自定义配置踩的一些坑,在不释放配置的前提下进行。

create-react-app@4.0.1 及创建出来的项目 react@17.0.1为例说明。

目前踩坑清单

  1. 路径别名配置
  2. 多个开发环境配置
  3. 多个代理环境配置
  4. node-sass与node版本不匹配问题
  5. 动态引进图片

路径别名配置

用脚手架创建的项目配置里面没有默认设置别名,那只通过相对路径去引入文件的话路径就会很长也不方便,那肯定要设置一个别名来缩短路径,让引入变得更方便和优雅。这里借助react-app-rewiredcustomize-cra两个插件。

react-app-rewired:此工具可以在不 eject 也不创建额外 react-scripts 的情况下修改脚手架内置的 webpack 配置,你将拥有 create-react-app 的一切特性,且可以根据你的需要去配置 webpackplugins, loaders 等。

customize-cra:利用react-app-rewired的核心功能来自定义create-react-app版本2和3的配置。

根目录创建config-overrides.js文件:

1
2
3
4
5
6
7
8
const { override, addWebpackAlias } = require('customize-cra')
const path = require('path')

module.exports = override(
addWebpackAlias({
['@']: path.resolve(__dirname, 'src')
})
)

然后修改package.json中运行命令:

1
2
3
4
5
6
{
// ...
"scripts": {
"start": "react-app-rewired start",
}
}

如果有引入ts的,还需在tsconfig.json中增加paths字段。但是在修改tsconfig.json配置之后,重新启动项目某些配置字段会被覆盖,就如paths

解决方案:在根目录创建一个paths.json文件,写上paths的配置,然后通过extends扩展字段将该文件引入tsconfig.json

paths.json文件如下:

1
2
3
4
5
6
7
8
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}

tsconfig.json文件:

1
2
3
4
{
// ...
"extends": "./paths.json"
}

这样就可以解决别名配置问题了。啪的一声,很快啊,项目就跑起来了。

多个开发环境配置

React脚手架提供开发环境配置仅限于testlocaldevelopmentproduction,对于我们自身开发有其它自定义环境的就显得不够了。那怎么去自定义开发环境呢,这里借助第三方插件cross-env来实现。

第一步,通过yarnnpm安装:

1
2
3
yarn add cross-env -D
// or
npm i cross-env -D

第二步,修改package.json文件里scripts的执行命令:

1
2
3
4
"scripts": {
"start:test": "cross-env REACT_APP_ENV=test react-app-rewired start",
"build:test": "cross-env REACT_APP_ENV=test react-app-rewired build"
},

通过这样的配置,就可以使用process.env.REACT_APP_ENV来获取到当前环境。其它自定义环境也是如此。

多个代理环境配置

如果是开发环境不需要像上面的自定义,只有一个的话,那可以直接在package.json文件加上代理配置proxy字段:

1
"proxy": "http://xxx"

但是如果有多个环境,这种配置就不合适了,所以多环境的时候还是需要借助第三方插件,这里选用http-proxy-middleware,这里比较方便的脚手架安装的时候这个插件已经有了,可以直接拿来用:

第一步,在src文件夹下新建名为setupProxy.js的文件,名字必须是这个;

第二步,在文件里面加入以下内容:

1
2
3
4
5
6
7
8
9
10
const proxy = require('http-proxy-middleware')
// 这一步是根据上面的配置 获取当前开发对应的环境
const runEnv = process.env.REACT_APP_ENV
// 接下来根据环境自定义需要代理的api和代理目标 并暴露出去 简单参考配置如下
module.exports = function(app) {
app.use('/api', {
target: 'http://xxx',
changeOrigin: true
})
}

根据自身业务补充上自定义的逻辑就可以实现多环境代理了。

node-sass与node版本不匹配

严格来说,这个坑不属于react配置上的坑,但是因为在项目基础建设的过程中遇到,因此记录进来。

脚手架已经内置了sass-loader,所以想要在项目里面使用sass预处理语言,只需安装node-sass就可以,无需再安装sass-loader

安装完node-sass之后项目跑不起来了,根据提示是node-sass版本问题,然后看了一下它的更新文档,有这么一个图:

从这个图可以知道,node-sassNodeJS的版本是有要求的,我的版本是14,但安装的node-sass5.0的,所以才会出现不支持的情况,这里更新一下node的版本或者安装4.14+node-sass都可以解决问题。

动态引进图片

本来打算使用require(path)来动态引入图片,通过传参来设置不同的背景图片,但是报错了,错误截图如下:

原因是webpack本身是一个预编译的打包工具,无法预测未知变量路径,require不能传纯变量路径,且path需要由三部分组成:目录+文件名+后缀,其实上图所示就是一个合格的路径。

解决方案1:require不使用纯变量,那就采用字符串+变量,如require('@/assets/images'+url),再写成一个工具函数:

1
2
3
4
const getImg = (url: string) => {
const imgObj = require('@/assets/images'+url)
return imgObj && imgObj.default
}

然后放到样式中,就可以实现动态渲染背景图片:

1
2
3
style={{
backgroundImage: `url(${getImg(props.bgUrl)})`,
}}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!