开发React应用很多人会使用create-react-app这个脚手架, 可以使用yarn eject
命令来自定义配置. 这篇文章就是讲解在eject之后如何配置自定义env
文件.
实际开发中, 我们一般会有三个环境:
- 本地开发环境(development)
- 线上生产环境(production)
- 测试环境(staging)
工作中会有这样的需求: 区分测试/正式环境的logo, 针对不同环境使用不同的google client id等等.我们知道线上环境和测试环境它们其实执行的都是yarn build
的命令打包的前端代码, NODE_ENV
都是"production", 那么我们如果进行区分呢?
我们可以使用.env文件
来解决此问题.
通过查看create-react-app的文档我们发现并不支持自定义env文件, 我们首先分析下执行yarn build
之后发生了什么, 在package.json看到实际上执行的scripts/build.js
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js"
},
scripts/build.js
文件
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
发现直接定义了NODE_ENV是production, 下面引入了../config/env
文件, 我们再来看env
文件
config/env.js
文件
'use strict';
const fs = require('fs');
const path = require('path');
const paths = require('./paths');
// Make sure that including paths.js after env.js will read .env variables.
delete require.cache[require.resolve('./paths')];
const NODE_ENV = process.env.NODE_ENV;
if (!NODE_ENV) {
throw new Error(
'The NODE_ENV environment variable is required but was not specified.'
);
}
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
const dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`,
// Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
`${paths.dotenv}.${NODE_ENV}`,
paths.dotenv,
].filter(Boolean);
dotenvFiles就是项目引入的.env
文件, 通过config/paths.js知道paths.dotenv
指的就是.env
, 那么在生产环境下面这里面引入的文件就是
const dotenvFiles = [
'.env.production.local',
'.env.local'
'.env.production',
'.env'
].filter(Boolean);
我们要做的就是修改dotenvFiles引入方法.
核心思路就是用process.env.MODE
来引入.env
文件
下面就是简单粗暴的解决方案:
- 在package.json的scripts中添加
build-staging
命令"build-staging": "node scripts/build-staging.js"
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"build-staging": "node scripts/build-staging.js",
"test": "node scripts/test.js"
},
- 在scripts中新建文件
build-staging.js
, 并将scripts/build.js
里面内容复制进来, 添加process.env.MODE = "staging";
scripts/build-staging.js
文件
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = "production";
process.env.NODE_ENV = "production";
process.env.MODE = "staging";
// 省略其余内容
- 修改
config/env.js
文件(新增const RUN_MODE = process.env.MODE || process.env.NODE_ENV;
修改dotenvFiles
)
const RUN_MODE = process.env.MODE || process.env.NODE_ENV;
const dotenvFiles = [
`${paths.dotenv}.${RUN_MODE}.local`,
NODE_ENV !== "test" && `${paths.dotenv}.local`,
`${paths.dotenv}.${RUN_MODE}`,
paths.dotenv,
].filter(Boolean);
- 在项目根目录添加
.env.staging
文件.
配置完毕, 当执行yarn build-staging
时就会引入.env.staging
文件.