环境变量

环境变量

默认环境变量

Umi 中提供了大量的 默认环境变量,这些变量可以帮助我们管理一些脚手架功能。

设置环境变量

package.json内修改启动命令,以添加对应环境变量。

示例代码如下:

{
/** 省略配置项 */
"scripts": {
/** 省略配置项 */
// 在start命令内添加UMI_ENV环境变量
"start": "cross-env REACT_APP_ENV=dev UMI_ENV=dev umi dev",
"start:dev": "cross-env REACT_APP_ENV=dev UMI_ENV=dev MOCK=none umi dev"
/** 省略配置项 */
}
/** 省略配置项 */
}

多运行环境管理

在开发中经常会有一些需求,根据应用运行的不同环境进行不同的逻辑处理。

比如,dev 环境使用 dev 的对应的 Url,而线上则使用 prod 对应的 Url。 或者,在某些特定的环境需要打开只有在该环境下才会生效的功能。

获取当前运行环境名称

在 Pro 的脚手架中有这样的一个环境变量 REACT_APP_ENV,该变量代表当前应用所处环境的具体名称。如 dev、test、pre、prod 等。

如若需要在 config 外的非 node 环境文件中使用该环境变量,则需要在 config 导出默认 defineConfig() 时配置 define{}

示例代码如下:

// config/config.ts
const { REACT_APP_ENV } = process.env;
export default defineConfig({
{/** 省略其他配置 */}
define: {
REACT_APP_ENV: REACT_APP_ENV || false,
}
{/** 省略其他配置 */}
});

使用该变量示例代码如下:

// src/components/RightContent/index.tsx
/** 省略其他代码 */
const GlobalHeaderRight: React.FC<{}> = () => {
/** 省略其他代码 */
return (
<Space className={className}>
<!-- 省略其他代码 -->
<!-- 在顶部右侧显示对应环境名称 -->
{REACT_APP_ENV && (
<span>
<Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
</span>
)}
</Space>
);
};

多环境多份配置文件

Pro 脚手架默认使用 Umi 作为底层框架,在 Umi 内可通过指定 UMI_ENV 环境变量来区分不同环境的配置文件UMI_ENV 需要在 package.json 内配置。

示例配置如下:

{
{/** 省略... */}
"scripts": {
"analyze": "cross-env ANALYZE=1 umi build",
"build": "umi build",
"build:dev": "cross-env REACT_APP_ENV=dev UMI_ENV=dev umi build",
"build:test": "cross-env REACT_APP_ENV=test UMI_ENV=test umi build",
"build:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=pre umi build",
"build:prod": "cross-env REACT_APP_ENV=prod UMI_ENV=prod umi build",
"deploy": "npm run site && npm run gh-pages",
"dev": "npm run start:dev",
{/** 省略... */}
"start": "cross-env REACT_APP_ENV=dev UMI_ENV=dev umi dev",
"start:dev": "cross-env REACT_APP_ENV=dev UMI_ENV=dev MOCK=none umi dev",
"start:no-mock": "cross-env REACT_APP_ENV=dev UMI_ENV=dev MOCK=none umi dev",
"start:no-ui": "cross-env REACT_APP_ENV=dev UMI_ENV=dev UMI_UI=none umi dev",
"start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=pre MOCK=none umi dev",
"start:test": "cross-env REACT_APP_ENV=test UMI_ENV=test MOCK=none umi dev",
{/** 省略... */}
},
{/** 省略... */}
}

UMI_ENVtest 时,则必须在 config 目录下配置 config.test.ts 文件来管理 test 环境下的不同变量,Umi 框架会在 deep merge 后形成最终配置。

示例代码如下:

// config/config.test.ts test环境对应的配置文件
import { defineConfig } from 'umi';
/**
* 导出的多环境变量命名约定:一律大写且采用下划线分割单词
* 注意:在添加变量后,需要在src/typing.d.ts内添加该变量的声明,否则在使用变量时IDE会报错。
*/
export default defineConfig({
define: {
API_URL: 'https://api-test.xxx.com', // API地址
API_SECRET_KEY: 'XXXXXXXXXXXXXXXX', // API调用密钥
},
});

变量使用示例:

// src/services/user.ts
import { request } from 'umi';
export async function query() {
// 使用API密钥调用用户接口
return request<API.CurrentUser[]>('${API_URL}/api/users', {
API_SECRET_KEY,
});
}

配置文件夹 config 下的结构:

ant-design-pro
├── config
│ ├── config.dev.ts
│ ├── config.test.ts
│ ├── config.pre.ts
│ ├── config.prod.ts
│ ├── config.ts
│ ├── proxy.ts
│ ├── routes.ts
│ ├── defaultSettings.ts
...

报错的处理方式

由于环境变量是直接使用,不会通过 window 对象的方式来使用,在 eslint 和 TypeScript 中都会报错。

eslint 中可以通过增加 globals 的配置来处理报错。代码看起来是这样的

{
"globals": {
"page": true
}
}

在 TypeScript 可以在 typings.d.ts 中进行定义:

示例代码如下:

// src/typings.d.ts
// ... 代码省略
declare const REACT_APP_ENV: 'test' | 'dev' | 'uat' | 'prod' | undefined;
// 以下变量声明对应config.[env].ts文件内define的变量
declare const API_URL: string;
declare const API_SECRET_KEY: string;

变量使用的原理

config 是 node 环境,所以可以直接用 process.env 来直接拿到环境变量,但是非 node 环境的代码中,使用 process.env 可能只会获得 NODE_ENV 这个约定俗成的变量,别的变量 webpack 并不会自动注入。

关于 process.envNODE_ENV 请看这里

这时候我们就需要使用 define,他是通过 define-plugin 来实现的这个特性,在 config 中将 node 的环境变量注入 define 配置中。

使用时需要注意的是我们不需要通过 window['key'] 的方式来使用它,而是直接使用。更具体的原理可以看一下define-plugin插件的实现。