环境变量

上次修改时间:2021-06-04 11:00:34

环境变量

默认环境变量

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插件的实现。