Skip to content

Commit

Permalink
Adding namespaced environment variables to DefinePlugin under REACT_APP_
Browse files Browse the repository at this point in the history
  • Loading branch information
eliperelman committed Aug 3, 2016
1 parent 11ec5d6 commit 2507eef
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 24 deletions.
21 changes: 21 additions & 0 deletions config/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

var REACT_APP = /^REACT_APP_/i;
var NODE_ENV = JSON.stringify(process.env.NODE_ENV || 'development');

module.exports = Object
.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce((env, key) => {
env['process.env.' + key] = JSON.stringify(process.env[key]);
return env;
}, {
'process.env.NODE_ENV': NODE_ENV
});
3 changes: 2 additions & 1 deletion config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var paths = require('./paths');
var env = require('./env');

module.exports = {
devtool: 'eval',
Expand Down Expand Up @@ -104,7 +105,7 @@ module.exports = {
template: paths.appHtml,
favicon: paths.appFavicon,
}),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }),
new webpack.DefinePlugin(env),
// Note: only CSS is currently hot reloaded
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin()
Expand Down
3 changes: 2 additions & 1 deletion config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var url = require('url');
var paths = require('./paths');
var env = require('./env');

var homepagePath = require(paths.appPackageJson).homepage;
var publicPath = homepagePath ? url.parse(homepagePath).pathname : '/';
Expand Down Expand Up @@ -127,7 +128,7 @@ module.exports = {
minifyURLs: true
}
}),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
new webpack.DefinePlugin(env),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
Expand Down
1 change: 1 addition & 0 deletions scripts/eject.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ prompt(
path.join('config', 'flow', 'file.js.flow'),
path.join('config', 'eslint.js'),
path.join('config', 'paths.js'),
path.join('config', 'env.js'),
path.join('config', 'polyfills.js'),
path.join('config', 'webpack.config.dev.js'),
path.join('config', 'webpack.config.prod.js'),
Expand Down
109 changes: 87 additions & 22 deletions template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ You can find the most recent version of this guide [here](https://github.com/fac
- [Sending Feedback](#sending-feedback)
- [Folder Structure](#folder-structure)
- [Available Scripts](#available-scripts)
- [npm start](#npm-start)
- [npm run build](#npm-run-build)
- [npm run eject](#npm-run-eject)
- [npm start](#npm-start)
- [npm run build](#npm-run-build)
- [npm run eject](#npm-run-eject)
- [How To...](#how-to)
- [Install a Dependency](#install-a-dependency)
- [Import a Component](#import-a-component)
- [Add a Stylesheet](#add-a-stylesheet)
- [Post-Process CSS](#post-process-css)
- [Add Images and Fonts](#add-images-and-fonts)
- [Install React Bootstrap](#install-react-bootstrap)
- [Display Lint Output in the Editor](#display-lint-output-in-the-editor)
- [Add Flow](#add-flow)
- [Deploy](#deploy)
- [Something Missing?](#something-missing)
- [Installing a Dependency](#installing-a-dependency)
- [Importing a Component](#importing-a-component)
- [Adding a Stylesheet](#adding-a-stylesheet)
- [Post-Processing CSS](#post-processing-css)
- [Adding Images and Fonts](#adding-images-and-fonts)
- [Installing React Bootstrap](#installing-react-bootstrap)
- [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor)
- [Adding Flow](#adding-flow)
- [Adding Custom Environment Variables](#adding-custom-environment-variables)
- [Deploying](#deploying)
- [Something Missing?](#something-missing)

## Sending Feedback

Expand Down Expand Up @@ -94,15 +95,15 @@ You don’t have to ever use `eject`. The curated feature set is suitable for sm

## How To...

### Install a Dependency
### Installing a Dependency

The generated project includes React and ReactDOM as dependencies. It also includes a set of scripts used by Create React App as a development dependency. You may install other dependencies (for example, React Router) with `npm`:

```
npm install --save <library-name>
```

### Import a Component
### Importing a Component

This project setup supports ES6 modules thanks to Babel.
While you can still use `require()` and `module.exports`, we encourage you to use [`import` and `export`](http://exploringjs.com/es6/ch_modules.html) instead.
Expand Down Expand Up @@ -150,7 +151,7 @@ Learn more about ES6 modules:
* [Exploring ES6: Modules](http://exploringjs.com/es6/ch_modules.html)
* [Understanding ES6: Modules](https://leanpub.com/understandinges6/read#leanpub-auto-encapsulating-code-with-modules)

### Add a Stylesheet
### Adding a Stylesheet

This project setup uses [Webpack](https://webpack.github.io/) for handling all assets. Webpack offers a custom way of “extending” the concept of `import` beyond JavaScript. To express that a JavaScript file depends on a CSS file, you need to **import the CSS from the JavaScript file**:

Expand Down Expand Up @@ -182,7 +183,7 @@ In development, expressing dependencies this way allows your styles to be reload

If you are concerned about using Webpack-specific semantics, you can put all your CSS right into `src/index.css`. It would still be imported from `src/index.js`, but you could always remove that import if you later migrate to a different build tool.

### Post-Process CSS
### Post-Processing CSS

This project setup minifies your CSS and adds vendor prefixes to it automatically through [Autoprefixer](https://github.com/postcss/autoprefixer) so you don’t need to worry about it.

Expand Down Expand Up @@ -215,7 +216,7 @@ becomes this:

There is currently no support for preprocessors such as Less, or for sharing variables across CSS files.

### Add Images and Fonts
### Adding Images and Fonts

With Webpack, using static assets like images and fonts works similarly to CSS.

Expand Down Expand Up @@ -251,7 +252,7 @@ Please be advised that this is also a custom feature of Webpack.

**It is not required for React** but many people enjoy it (and React Native uses a similar mechanism for images). However it may not be portable to some other environments, such as Node.js and Browserify. If you prefer to reference static assets in a more traditional way outside the module system, please let us know [in this issue](https://github.com/facebookincubator/create-react-app/issues/28), and we will consider support for this.

### Install React Bootstrap
### Installing React Bootstrap

You don’t have to use React Bootstrap together with React but it is a popular library for integrating Bootstrap with React apps. If you need it, you can integrate it with Create React App by following these steps:

Expand Down Expand Up @@ -279,7 +280,7 @@ import { Navbar, Jumbotron, Button } from 'react-bootstrap';

Now you are ready to use the imported React Bootstrap components within your component hierarchy defined in the render method. Here is an example [App.js](https://github.com/manavsehgal/react-eshop/blob/master/src/App.js) redone using React Bootstrap.

### Display Lint Output in the Editor
### Displaying Lint Output in the Editor

>Note: this feature is available with `react-scripts@0.2.0` and higher.
Expand Down Expand Up @@ -310,7 +311,7 @@ npm install -g eslint babel-eslint eslint-plugin-react eslint-plugin-import esli

We recognize that this is suboptimal, but it is currently required due to the way we hide the ESLint dependency. The ESLint team is already [working on a solution to this](https://github.com/eslint/eslint/issues/3458) so this may become unnecessary in a couple of months.

### Add Flow
### Adding Flow

Flow typing is currently [not supported out of the box](https://github.com/facebookincubator/create-react-app/issues/72) with the default `.flowconfig` generated by Flow. If you run it, you might get errors like this:

Expand Down Expand Up @@ -366,7 +367,71 @@ module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|svg\|ttf\|woff\|woff2\|mp4\|w

We will consider integrating more tightly with Flow in the future so that you don’t have to do this.

### Deploy
### Adding Custom Environment Variables

> Note: this feature is available with `react-scripts@0.3.0` and higher.
Your project can consume variables declared in your environment as if they were declared locally in your JS files. By
default you will have `NODE_ENV` defined for you, and any other environment variables starting with
`REACT_APP_`. These environment variables will be defined for you on `process.env`. For example, having an environment
variable named `REACT_APP_SECRET_CODE` will be exposed in your JS as `process.env.REACT_APP_SECRET_CODE`, in addition
to `process.env.NODE_ENV`.

These environment variables can be useful for displaying information conditionally based on where the project is
deployed or consuming sensitive data that lives outside of version control.

First, you need to have environment variables defined, which can vary between OSes. For example, let's say you wanted to
consume a secret defined in the environment inside a `<form>`:

```jsx
<h6>Hello, Admin!<h6>

<small>You are running this application in <strong>{process.env.NODE_ENV}</strong> mode.</small>

<form>
<input type="hidden" defaultValue={process.env.REACT_APP_SECRET_CODE} />
</form>
```

The above form is looking for a variable called `REACT_APP_SECRET_CODE` from the environment. In order to consume this
value, we need to have it defined in the environment:

#### Windows Cmd

```cmd
set REACT_APP_SECRET_CODE=abcdef && npm start
```

#### Bash/Unix shells

```bash
REACT_APP_SECRET_CODE=abcdef npm start
```

> Note: Defining environment variables in this manner is temporary for the life of the shell session. Setting
permanent environment variables is outside the scope of these docs.

With our environment variable defined, we start the app and consume the values. Remember that the `NODE_ENV`
variable will be set for you automatically. When you load the app in the browser and inspect the `<input>`, you will see
its value set to `abcdef`, and the bold text will show the environment provided when using `npm start`:

```html
<h6>Hello, Admin!</h6>
<small>You are running this application in <strong>development</strong> mode.</small>
<form>
<input type="hidden" value="abcdef" />
</form>
```

Having access to the `NODE_ENV` is also useful for performing actions conditionally:

```js
if (process.env.NODE_ENV !== 'production') {
analytics.disable();
}
```

### Deploying

#### GitHub Pages

Expand Down

0 comments on commit 2507eef

Please sign in to comment.