简体   繁体   中英

How Do I Build For A UAT Environment Using React?

According to the React docs you can have development , test and production envs.

The value of NODE_ENV is set automatically to development (when using npm start ), test (when using npm test ) or production (when using npm build ). Thus, from the point of view of create-react-app, there are only three environments.

I need to change root rest api urls based on how I am deployed. eg

  • development: baseURL = 'http://localhost:3004';
  • test: baseURL = 'http://localhost:8080';
  • uat: baseURL = 'http://uat.api.azure.com:8080';
  • production: baseURL = 'http://my.cool.api.com';

How do I configure a UAT environment for react if it only caters for dev, test and prod?

What would my javascript, package.json and build commands look like to switch these values automatically?

Like John Ruddell wrote in the comments , we should still use NODE_ENV=production in a staging environment to keep it as close as prod as possible. But that doesn't help with our problem here.

The reason why NODE_ENV can't be used reliably is that most Node modules use NODE_ENV to adjust and optimize with sane defaults, like Express, React, Next, etc. Next even completely changes its features depending on the commonly used values development , test and production .

So the solution is to create our own variable, and how to do that depends on the project we're working on.

Additional environments with Create React App (CRA)

The documentation says:

Note: You must create custom environment variables beginning with REACT_APP_ . Any other variables except NODE_ENV will be ignored to avoid accidentally exposing a private key on the machine that could have the same name .

It was discussed in an issue where Ian Schmitz says:

Instead you can create your own variable like REACT_APP_SERVER_URL which can have default values in dev and prod through the .env file if you'd like, then simply set that environment variable when building your app for staging like REACT_APP_SERVER_URL=... npm run build .

A common package that I use is cross-env so that anyone can run our npm scripts on any platform.

"scripts": {
  "build:uat": "cross-env REACT_APP_SERVER_URL='http://uat.api.azure.com:8080' npm run build"

Any other JS project

If we're not bound to CRA, or have ejected , we can easily configure any number of environment configurations we'd like in a similar fashion.

Personally, I like dotenv-extended which offers validation for required variables and default values.

Similarly, in the package.json file:

"scripts": {
  "build:uat": "cross-env APP_ENV=UAT npm run build"

Then, in an entry point node script (one of the first script loaded, eg required in a babel config):

const dotEnv = require('dotenv-extended');

// Import environment values from a .env.* file
const envFile = dotEnv.load({
  path: `.env.${process.env.APP_ENV || 'local'}`,
  defaults: 'build/env/.env.defaults',
  schema: 'build/env/.env.schema',
  errorOnMissing: true,
  silent: false,
});

Then, as an example, a babel configuration file could use these like this:

const env = require('./build/env');

module.exports = {
  plugins: [
    ['transform-define', env],
  ],
};

Runtime configuration

John Ruddell also mentioned that one can detect at runtime the domain the app is running off of.

function getApiUrl() {
  const { href } = window.location;

  // UAT
  if (href.indexOf('https://my-uat-env.example.com') !== -1) {
    return 'http://uat.api.azure.com:8080';
  }

  // PROD
  if (href.indexOf('https://example.com') !== -1) {
    return 'http://my.cool.api.com';
  }

  // Defaults to local
  return 'http://localhost:3004';
}

This is quick and simple, works without changing the build/CI/CD pipeline at all. Though it has some downsides:

  • All the configuration is "leaked" in the final build,
  • It won't benefit from dead-code removal at minification time when using something likebabel-plugin-transform-define or Webpack's DefinePlugin resulting in a slightly bigger file size.
  • Won't be available at compile time.
  • Trickier if using Server-Side Rendering (though not impossible)

To have multiple environments in a React.js application you can use this plugin env-cmd from NPM

And after that Create the three files as per your need. For example if you want to setup dev, stag and prod environments you can write your commands like this.

"start:dev": "env-cmd -f dev.env npm start", // dev env
"build:beta": "env-cmd -f stag.env npm run build", // beta env
"build": "react-scripts build", // prod env using .env file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM