通常情况下,开发环境和线上环境用的 API 的 URL 不是同一个,所以并不能将 URL 写死,而是要根据不同的环境,使用不同的 API.
内置环境
create-react-app
创建的项目有内置的环境变量 NODE_ENV
, 在 JavaScript 代码中可通过 process.env.NODE_ENV
读取它。
NODE_ENV
默认有三个可能的值,分别是 development
, test
和 production
, 对应开发,测试,生产环境。
运行 npm start
, NODE_ENV
的值为 development
; npm run test
则是 test
; npm run build
则对应 prodution
.
比如开发环境的 API 的 URL 为 urlDev
, 生产环境的 URL 为 urlProd
, 就可通过环境变量,判断当前环境,使用相应的 URL:
let env = process.env.NODE_ENV
let baseUrl = ''
if (env === 'development') {
baseUrl = urlDev
} else if (env === 'production') {
baseUrl = urlProd
}
get(baseUrl) // 伪代码,表示请求动作
...
一般来说,这三个值够用了。
但是需要更多环境的话呢,比如,需要一个开发环境,一个测试环境,一个 UAT (User Acceptance Testing) 环境,一个 stage 环境,一个 production 环境。
掰掰手指数一数,发现上面三兄弟不够用了。
这个时候需要自定义环境变量。
多环境
分析
求助于文档,给了两个方法:
- shell 环境添加,写在命令行,类似运行下面这样的命令
set "REACT_APP_SECRET_CODE=abcdef" && npm start
但是这种方式只是在 Shell 中添加临时的变量,JavaScript 是读取不到的。
-
在
.env
文件添加,即在项目的根目录添加一个名为.env
的文件,在里面添加环境变量,这样的变量在 JavaScript 是可以读取到的。还有不同的文件名可在不同的环境进行覆盖,比如将文件命名为
.env.development
, 在开发环境即可读取文件内定义的变量。同样,.env.test
和.env.production
分别对应测试环境和生产环境。这种方式,显而易见,只支持内置的三个环境。
文档里面还透漏一个重要信息,react 只读取 REACT_APP
开头的变量,其他的,表示不认识。
比如简单写个 MY_ENV
, 是会被 React
忽略的,而 REACT_APP_ENV
就会被读取。
配置
有个思路,就是从命令行入手,然后搞一个 JavaScript 可以读到的永久环境变量。
这里需要 cross-env
, cross-env
设计是为了定义全平台兼容的环境变量命令,因为 Windows 在设置环境变量的命令会出现阻塞问题。
首先安装 cross-env
:
npm install --save-dev cross-env
然后在 package.json
的 scripts
里面添加代码。
比如我要设置 stage 环境下的环境变量 REACT_APP_ENV
为 stage
, 只需在 package.json
添加如下代码
"build:stage": "cross-env REACT_APP_ENV=stage react-scripts build"
其中 cross-env REACT_APP_ENV=stage
定义了 REACT_APP_ENV
为 stage
.
然后得到:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"build:stage": "cross-env REACT_APP_ENV=stage react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
这样一来,运行 npm run build:stage
打包之后,process.env.REACT_APP_ENV
的值即为 'stage'
.
其他要添加什么环境,以此类推。