diff --git a/packages/react-scripts/config/env.js b/packages/react-scripts/config/env.js index c018467a95b..0097f3cf304 100644 --- a/packages/react-scripts/config/env.js +++ b/packages/react-scripts/config/env.js @@ -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; diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 76397756040..915b1a83865 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -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'), @@ -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'), @@ -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'), diff --git a/packages/react-scripts/fixtures/kitchensink/.env b/packages/react-scripts/fixtures/kitchensink/.env index 3e6e8a5a360..3e2f7b14a73 100644 --- a/packages/react-scripts/fixtures/kitchensink/.env +++ b/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 diff --git a/packages/react-scripts/fixtures/kitchensink/.env.development b/packages/react-scripts/fixtures/kitchensink/.env.development new file mode 100644 index 00000000000..cc10be5e6d8 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/.env.development @@ -0,0 +1,2 @@ +REACT_APP_X = x-from-development-env +REACT_APP_DEVELOPMENT = development diff --git a/packages/react-scripts/fixtures/kitchensink/.env.local b/packages/react-scripts/fixtures/kitchensink/.env.local new file mode 100644 index 00000000000..b248646bdad --- /dev/null +++ b/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 diff --git a/packages/react-scripts/fixtures/kitchensink/.env.production b/packages/react-scripts/fixtures/kitchensink/.env.production new file mode 100644 index 00000000000..ec8bdcb54f3 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/.env.production @@ -0,0 +1,2 @@ +REACT_APP_X = x-from-production-env +REACT_APP_PRODUCTION = production diff --git a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js index b90d12ab12e..89d19fcf4b1 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js @@ -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 () => { diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js index a8a1e98fe71..55ae368e437 100644 --- a/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js @@ -10,7 +10,16 @@ import React from 'react'; export default () => ( - - {process.env.REACT_APP_FILE_ENV_MESSAGE}. + + + {process.env.REACT_APP_ORIGINAL_1} + + + {process.env.REACT_APP_ORIGINAL_2} + + + {process.env.REACT_APP_DEVELOPMENT}{process.env.REACT_APP_PRODUCTION} + + {process.env.REACT_APP_X} ); diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js index fe4ec959d4d..da9004f9ee6 100644 --- a/packages/react-scripts/scripts/build.js +++ b/packages/react-scripts/scripts/build.js @@ -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'); diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 12cce8ed313..b44fc44c907 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -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'); diff --git a/packages/react-scripts/scripts/test.js b/packages/react-scripts/scripts/test.js index 5c395999d97..ef333e6c004 100644 --- a/packages/react-scripts/scripts/test.js +++ b/packages/react-scripts/scripts/test.js @@ -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); diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index 933e9b0cdcb..cc66b9526bb 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -752,6 +752,24 @@ To define permanent environment variables, create a file called `.env` in the ro REACT_APP_SECRET_CODE=abcdef ``` + + These variables will act as the defaults if the machine does not explicitly set them.
Please refer to the [dotenv documentation](https://github.com/motdotla/dotenv) for more details. diff --git a/packages/react-scripts/template/gitignore b/packages/react-scripts/template/gitignore index 927d17bb9c5..d30f40ef442 100644 --- a/packages/react-scripts/template/gitignore +++ b/packages/react-scripts/template/gitignore @@ -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* -