0

I have 2 AWS EC2 instances running.

1 EC2(API_BACK_END) instance I am using as an API backend server with NODE Express js talking to RDS

1 EC2 instance i am using to deploy React Front end (using create-react-app) with NodeJS, I am running it in dev mode (I haven't built the build folder), I can confirm I am able to hit the API_BACK_END using the following hack

const BK_END_HOST = process.env.NODE_ENV !== 'development' ? 
              "localhost:3000" : process.env.REACT_APP_BACK_END_HOST_URL ;

I have not created the build version, I just do a npm start to run it in dev mode, I wanted to make sure I have the correct Network settings on AWS and I am able to the backend.

Problem is that I am confused as to what changes I need to make when I do npm run build, I have been reading a lot of articles from past few days but I am unsure as to what needs to be done.

This is how I am calling my endpoint

    callApi = async () => {
    console.log("---------------",BK_END_HOST);
    const response = await fetch(BK_END_HOST+'/MLNumbers');
    const body = await response.json();
    if (response.status !== 200) throw Error(body.message);
    const ret = body.melbCases[0].cases;
    console.log(ret);
    return ret;
  }; 

do I need to have express in the front end too? if so how will I call my backend from it, I need some way to proxy the api calls to my API_BACK_END server, I came across http-prox-middleware but that's only For dev environment.

M_J
  • 61
  • 10
  • Does `localhost:3000` link to your production url? Since `!== ''development"` could mean that you built the application and therefore is in production. If you replace localhost:3000 with the url of the production express url you want then that should solve your problem. – Brandon Aug 11 '20 at 13:14
  • No it isn't, my environment variable was never picked up since I am running it it development, I forced it by making it false using `!==`, did that to make sure there is no problem with talking to the other EC2 instance, – M_J Aug 11 '20 at 13:19
  • okay, you can try something like this https://riptutorial.com/node-js/example/10101/setting-node-env--production- – Brandon Aug 11 '20 at 13:50

1 Answers1

3

In a backend apps or api (java, nodejs, php, python, etc) is best practice to use environment variables instead hardcoded in properties file because we can generate just one artifact for all of our environments(development, staging, production). Before its start, we only need to export the required variables and that's all.

But what happen in modern applications called : frontend rendering frameworks, spa, javascript apps which are developed with react, angular, vue, etc ?

  • react, angular or vue are javascript frameworks to be loaded in browsers, not in the server like nodejs javascript
  • Environment variables are not accessible from a browser. process.env offered by cra framework(react) is an "emulation" implemented with webpack in the deep of this framework. As a quick summary this framework reads the operative system variables and crete a javascript global variable (process.env) ready to use in your react files. Check this
  • any variable used in these apps, are accessible with a simple browser inspection because these variables are hardcoded in the bowels of bundle.js, dist.js or whatever the build result is called. So no matter what you invent, if your javascript needs some variable, this must exist in the browser so it will be accessible by your users.

So if your react app(javascript) needs the classic api url to exchange information, you will need a variable in any part of your javascript. Check this to understand how can we inject variables in javascript apps.

Also remember that to deploy your builded javascript application could be deployed from basic tools (because the result are just static files: index.html, css, bundle.js, etc) to advanced servers:

(1)Basic approach

Before build process, just change the localhost:3000 to acme.api.com in some of your javascript files like, constants.js, setting.js, configuration.js, etc

  • Advantage: easy and not external tools are required
  • Disadvantage:
    • devops is broken because a human is required in build process
    • will need to repeat this process before any of your environments : dev, testing, staging, production, etc
    • a new build process is required for any of your environments : dev, testing, staging, production, etc

(2)Medium Approach

Replace your constants.js to the classic .properties file, .env file or any kind of file in which we set all the variables that change when artifact is moved from one environment to another.

So you can have one properties file by environment close to your source code or outside of source code like your build server:

  • src/resources/dev/app.properties or .env.dev
  • src/resources/staging/app.properties or .env.staging
  • src/resources/prodution/app.properties or .env.prodution

And finally with some trick you could switch between these files. package.json sample

"scripts": {
  "build:dev": "export $(cat .env.dev | xargs) && react-scripts build",
  "build:dev": "export $(cat .env.staging | xargs) && react-scripts build",
  "build:dev": "export $(cat .env.dev | prodution) && react-scripts build"
}

Or play with the name of these files and some var like NODE_ENVIRONMENT. Check these links to view more examples:

This approach is similar to your current workaround. Check this: https://dev.to/rishikeshvedpathak/react-environment-specific-builds-using-env-with-cra-and-env-cmd-296b

Also check Angular cli limitation: Every environment requires a separate build

(3) Advanced approach

What if your javascript app at the first invocation, get or retrieve the configurations from a kind of rest endpoint?

  • Advantage:
    • easy
    • one build for all your envinronments
    • open the posibility to hot reload of configurations in the javascript apps. Something like: Hey, user! refresh your web to view the new season effect.
    • devops process is happy
  • Disadvantage:
    • a new platform or a simple endpoint is required. This is in charge of give us the variables
    • intermediate javascript knoledge is required to perform this ajax invocation at the first user invocation

On my apps I called /settings to this endpoint. This returns a json response with several variables like:

  • api base urls
  • some quotes to home page
  • background colors
  • any configuration parameters required by the frontend app
  • etc

Take a look to my server: https://github.com/utec/geofrontend-server. It was designed for requirements exactly like yours. I think the readme is good, but contact me with an issue if you need some help. As a summary if you want to use this nodejs server for your app, the steps will be:

  • create one properties file with environment vars
  • add one dependency to your react app package.json
  • just run
JRichardsz
  • 14,356
  • 6
  • 59
  • 94
  • I have learnt a few more things and you answered some other questions that I had with react and software architecture design capabilities. I will ask in a different way. In my react app my component makes the rest api call to retrieve whatever data from server(which is another ec2 instance) in order to take it to production when I do npm run build then in order for node at front end to serve that build folder do I need to do anything to my backend server for it to work with the front end? – M_J Aug 12 '20 at 03:13