React配置不同环境的全局常量,无需插件适配多环境

1,051 阅读3分钟

目的

不知各位大佬开发时有没有遇到我遇到的问题

  1. mock请求url和生产环境的请求url不一样,编译前手动修改baseUrl不够优雅
  2. 需要编译多次放到多个服务器(例如测试服务器),编译完一个再编译另一个不够爽,想要同时编译两个放到不同文件夹
  3. 需要一个全局配置对象,在React代码中可随时无需引入地拿到这个对象

下面将通过process.env实现多环境配置解决如上问题,大佬们有别的方案也欢迎在评论区讨论

  • create-react-app 版本:5.0.1

一、生成配置文件

如果项目文件中没有webpack.config.js和对应build.js``start.js等配置文件,需要运行以下命令生成

npm run eject

运行以上命令前需要了解,这个命令是不可逆的,我们看看creat-react-app对这个命令的解释

Note: this is a one-way operation. Once you eject, you can't go back!

If you aren't satisfied with the build tool and configuration choices, you can eject at >any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.

You don't have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.

大概意思这个操作不可逆,当对构建工具和配置选择不满意时,运行此命令会将所有的配置文件和可传递的依赖项(webpack、Babel、ESLint等)直接复制到您的项目中,然后就可以控制这些配置了

运行命令后会在根目录生成以下文件

image.png image.png

二、配置环境常量

1、添加配置项

在生成的start.js中添加所需要的配置,个人习惯用一个对象集合所有配置

process.env.REACT_APP_CONFIG = {
  baseUrl: "http://localhost:3001",
  socketUrl: "http://localhost:3120",
}

注意:REACT_APP_CONFIG可以改成其他名称,但必须以REACT_APP_开头,vue就以VUE_APP_开头

2、获取配置

webpack.config.js文件最开头中添加以下代码,看能否拿到配置

const $config = process.env.REACT_APP_CONFIG
console.log("🚀  $config: ", $config, $config.baseUrl);

重启看打印发现拿到的是[object Object]

image.png

原来这个方法会将值转为字符串再传递过来,那怎么解决呢?

好办!我自己把对象转为字符串总行了吧

3、改造配置项为字符串
//start.js
const $config = {
  baseUrl: "http://localhost:3001",
  socketUrl: "http://localhost:3120",
}
process.env.REACT_APP_CONFIG =  JSON.stringify($config);//手动转字符串

//webpack.config.js
const $config = JSON.parse(process.env.REACT_APP_CONFIG);

再重启打印可以看到已经可以拿到配置对象了

image.png

4、将配置放到全局

仅仅在配置文件拿到可不够,下面把配置放到全局环境

webpack.config.js中搜索new HtmlWebpackPlugin,通过这个插件给index.html传递配置

image.png

在以上插件中加上我们之前拿到的配置对象

new HtmlWebpackPlugin(
        Object.assign(
          {
            $config: JSON.stringify($config),
            //这次聪明了,直接传字符串吧
          },
          ...

然后在index.html中将配置挂载到window中,在 <head></head>中添加如下代码

<script>
   var $config = "<%= htmlWebpackPlugin.options.$config%>";
   $config = JSON.parse($config);
   console.log("🚀index.html $config:", $config);
</script>

image.png

重启发现报错了,原来"<%= htmlWebpackPlugin.options.$config%>"是用引号包起来的,再传递字符串的话相当于有两重引号了

这里用一个巧办法解决,将引号改成反引号,因为模板字符串是可以包含单双引号的

   var $config = `<%= htmlWebpackPlugin.options.$config%>`;

重启后发现可以通过window拿到配置了!这样在React中也随时能通过$config拿到配置了

image.png

5、配置生产环境

以上只做了开发环境配置,生产环境其实是一样的配置方法,将配置复制到build.js,并改成生产配置

const $config = {
  baseUrl: "http://192.168.1.1:3001",//生产环境url
  socketUrl: "http://192.168.1.1:3120",
};
process.env.REACT_APP_CONFIG = JSON.stringify($config);
6、改造baseUrl

此时axios的baseURL就可以使用配置文件中的配置了

axios.defaults.baseURL = $config.baseUrl;

三、配置多个打包目录

如果有部署到测试环境的需求,可以进行以下操作

1、配置test环境

复制一个build.js文件命名为build-test.js,并修改里面的配置

const $config = {
  baseUrl: "http://192.168.1.1:3001",//test环境的url
  socketUrl: "http://192.168.1.1:3120",
}
process.env.REACT_APP_CONFIG =  JSON.stringify($config);

package.json中添加build-test命令,此时执行npm run build-test就会以build-test.js内配置来打包

 "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "build-test": "node scripts/build-test.js",
    "test": "node scripts/test.js"
  },
2、配置打包目录

通过搜索buildPath可以看到paths.js文件已经对打包路径做了配置,这就好办了

const buildPath = process.env.BUILD_PATH || 'build';

只要在各自配置文件配置process.env.BUILD_PATH即可

//build.js
process.env.BUILD_PATH = 'build-online'

//build-test.js
process.env.BUILD_PATH = 'build-test'

这时运行两个命令就可以看到分别放在不同目录下了

npm run build
npm run build-test

image.png

3、gitignore

最后别忘记改gitignore

根目录.gitignore文件

# production
/build
/build-online
/build-test

这样就能愉快地进行打包了,也能随时按需添加全局常量~