Skip to content

Commit

Permalink
Feature/different env config files #1343 (#1344)
Browse files Browse the repository at this point in the history
* support different env configs.

* fomrat code

* Hide doc

* Slightly rework the PR

* Remove .env in default template
* Use just one entry in the paths
* Unify env.js and loadEnv.js

* Oops, forgot these folks
  • Loading branch information
tuchk4 authored and gaearon committed May 12, 2017
1 parent 2de95c4 commit 80a7fc3
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 22 deletions.
30 changes: 30 additions & 0 deletions packages/react-scripts/config/env.js
Expand Up @@ -10,6 +10,36 @@
// @remove-on-eject-end
'use strict';

var fs = require('fs');
var paths = require('./paths');

var 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
var dotenvFiles = [
paths.dotenv + '.' + NODE_ENV + '.local',
paths.dotenv + '.' + NODE_ENV,
paths.dotenv + '.local',
paths.dotenv,
];
// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
require('dotenv').config({
silent: true,
path: dotenvFile,
});
}
});

// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
const REACT_APP = /^REACT_APP_/i;
Expand Down
3 changes: 3 additions & 0 deletions packages/react-scripts/config/paths.js
Expand Up @@ -74,6 +74,7 @@ function getServedPath(appPackageJson) {

// config after eject: we're in ./config/
module.exports = {
dotenv: resolveApp('.env'),
appBuild: resolveApp('build'),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
Expand All @@ -95,6 +96,7 @@ function resolveOwn(relativePath) {

// config before eject: we're in ./node_modules/react-scripts/config/
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp('build'),
appPublic: resolveApp('public'),
Expand Down Expand Up @@ -124,6 +126,7 @@ if (
__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1
) {
module.exports = {
dotenv: resolveOwn('template/.env'),
appPath: resolveApp('.'),
appBuild: resolveOwn('../../build'),
appPublic: resolveOwn('template/public'),
Expand Down
4 changes: 3 additions & 1 deletion packages/react-scripts/fixtures/kitchensink/.env
@@ -1 +1,3 @@
REACT_APP_FILE_ENV_MESSAGE=fromtheenvfile
REACT_APP_X = x-from-original-env
REACT_APP_ORIGINAL_1 = from-original-env-1
REACT_APP_ORIGINAL_2 = from-original-env-2
2 changes: 2 additions & 0 deletions packages/react-scripts/fixtures/kitchensink/.env.development
@@ -0,0 +1,2 @@
REACT_APP_X = x-from-development-env
REACT_APP_DEVELOPMENT = development
2 changes: 2 additions & 0 deletions packages/react-scripts/fixtures/kitchensink/.env.local
@@ -0,0 +1,2 @@
REACT_APP_X = x-from-original-local-env
REACT_APP_ORIGINAL_2 = override-from-original-local-env-2
2 changes: 2 additions & 0 deletions packages/react-scripts/fixtures/kitchensink/.env.production
@@ -0,0 +1,2 @@
REACT_APP_X = x-from-production-env
REACT_APP_PRODUCTION = production
Expand Up @@ -16,8 +16,27 @@ describe('Integration', () => {
const doc = await initDOM('file-env-variables');

expect(
doc.getElementById('feature-file-env-variables').textContent
).to.equal('fromtheenvfile.');
doc.getElementById('feature-file-env-original-1').textContent
).to.equal('from-original-env-1');
expect(
doc.getElementById('feature-file-env-original-2').textContent
).to.equal('override-from-original-local-env-2');

if (process.env.NODE_ENV === 'production') {
expect(doc.getElementById('feature-file-env').textContent).to.equal(
'production'
);
expect(doc.getElementById('feature-file-env-x').textContent).to.equal(
'x-from-production-env'
);
} else {
expect(doc.getElementById('feature-file-env').textContent).to.equal(
'development'
);
expect(doc.getElementById('feature-file-env-x').textContent).to.equal(
'x-from-development-env'
);
}
});

it('NODE_PATH', async () => {
Expand Down
Expand Up @@ -10,7 +10,16 @@
import React from 'react';

export default () => (
<span id="feature-file-env-variables">
{process.env.REACT_APP_FILE_ENV_MESSAGE}.
<span>
<span id="feature-file-env-original-1">
{process.env.REACT_APP_ORIGINAL_1}
</span>
<span id="feature-file-env-original-2">
{process.env.REACT_APP_ORIGINAL_2}
</span>
<span id="feature-file-env">
{process.env.REACT_APP_DEVELOPMENT}{process.env.REACT_APP_PRODUCTION}
</span>
<span id="feature-file-env-x">{process.env.REACT_APP_X}</span>
</span>
);
7 changes: 2 additions & 5 deletions packages/react-scripts/scripts/build.js
Expand Up @@ -20,11 +20,8 @@ process.on('unhandledRejection', err => {
throw err;
});

// Load environment variables from .env file. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
require('dotenv').config({ silent: true });
// Ensure environment variables are read.
require('../config/env');

const chalk = require('chalk');
const fs = require('fs-extra');
Expand Down
7 changes: 2 additions & 5 deletions packages/react-scripts/scripts/start.js
Expand Up @@ -19,11 +19,8 @@ process.on('unhandledRejection', err => {

process.env.NODE_ENV = 'development';

// Load environment variables from .env file. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
require('dotenv').config({ silent: true });
// Ensure environment variables are read.
require('../config/env');

const fs = require('fs');
const chalk = require('chalk');
Expand Down
7 changes: 2 additions & 5 deletions packages/react-scripts/scripts/test.js
Expand Up @@ -20,11 +20,8 @@ process.on('unhandledRejection', err => {
throw err;
});

// Load environment variables from .env file. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
require('dotenv').config({ silent: true });
// Ensure environment variables are read.
require('../config/env');

const jest = require('jest');
const argv = process.argv.slice(2);
Expand Down
18 changes: 18 additions & 0 deletions packages/react-scripts/template/README.md
Expand Up @@ -739,6 +739,24 @@ To define permanent environment variables, create a file called `.env` in the ro
REACT_APP_SECRET_CODE=abcdef
```

<!--
TODO: uncomment (and tweak) the doc for 0.10
What .env* files are used?
* `.env` - Default
* `.env.development`, `.env.test`, `.env.production` - Environment-specific settings.
* `.env.local` - Local overrides. This file is loaded for all environments except test.
* `.env.development.local`, `.env.test.local`, `.env.production.local` - Local overrides of environment-specific settings.
Files priority (file is skipped if does not exist):
* npm test - `.env.test.local`, `env.test`, `.env.local`, `.env`
* npm run build - `.env.production.local`, `env.production`, `.env.local`, `.env`
* npm start - `.env.development.local`, `env.development`, `.env.local`, `.env`
Priority from left to right.
-->

These variables will act as the defaults if the machine does not explicitly set them.<br>
Please refer to the [dotenv documentation](https://github.com/motdotla/dotenv) for more details.

Expand Down
7 changes: 5 additions & 2 deletions packages/react-scripts/template/gitignore
Expand Up @@ -11,8 +11,11 @@

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

0 comments on commit 80a7fc3

Please sign in to comment.