開發(fā)React應(yīng)用很多人會使用create-react-app這個腳手架, 可以使用yarn eject命令來自定義配置. 這篇文章就是講解在eject之后如何配置自定義env文件.
實際開發(fā)中, 我們一般會有三個環(huán)境:
- 本地開發(fā)環(huán)境(development)
- 線上生產(chǎn)環(huán)境(production)
- 測試環(huán)境(staging)
工作中會有這樣的需求: 區(qū)分測試/正式環(huán)境的logo, 針對不同環(huán)境使用不同的google client id等等.我們知道線上環(huán)境和測試環(huán)境它們其實執(zhí)行的都是yarn build的命令打包的前端代碼, NODE_ENV都是"production", 那么我們?nèi)绻M行區(qū)分呢?
我們可以使用.env文件來解決此問題.

通過查看create-react-app的文檔我們發(fā)現(xiàn)并不支持自定義env文件, 我們首先分析下執(zhí)行yarn build之后發(fā)生了什么, 在package.json看到實際上執(zhí)行的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');
發(fā)現(xiàn)直接定義了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, 那么在生產(chǎn)環(huán)境下面這里面引入的文件就是
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里面內(nèi)容復(fù)制進來, 添加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";
// 省略其余內(nèi)容
- 修改
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文件.
配置完畢, 當執(zhí)行yarn build-staging時就會引入.env.staging文件.