How to make UI code dev configurable? - node.js

I have a reactjs app deployed on AWS Elastic Beanstalk environment that used Cognito for authentication. I need to make my front-end code DEV configurable using environment variables with database and Cognito.
Does anyone know how to achieve that?

I don't think you can read any ENV vars from your client side reactjs app, instead you'll need a server side technology to do that. Elastic Beanstalk lets you enter the environment variables for each environment using the management panel. Add your ENV var and these variables will be attached to the process.env object
const config = {};
config.db = {
database : process.env.DB_HOST || 'your-db-host'
database : process.env.DB_USER || 'your-db-user'
database : process.env.DB_PASSWORD || 'your-db-pwd'
};
export default config;

I am using create-react-app and here is my build script
"build": "sh -ac '. ./.env.${REACT_APP_ENV}; react-scripts build'",
"build:prod": "REACT_APP_ENV=prod npm run-script build",
"build:staging": "REACT_APP_ENV=staging npm run-script build",
It requires you to have files like .env.prod and .env.staging files in your root folder to set the environment variables for their respective environments , you can add other scripts as well for example to add something for local environment i would add
"build:local": "REACT_APP_ENV=local npm run-script build"
In package.json and then add .env.local file in root folder that has my all my local specific env. variables.
Run the build command for CRA as
npm run build:local
(for build with local env. variables)

Related

Can you set a NODE_ENV variable for a staging site url in react?

I'm using the following NODE_ENV variable to use a different API depending on whether i'm in development mode or on the live site
process.env.NODE_ENV === 'development'
I also have a staging site hosted which i would like to use the same API as the development (local) project. Is there a way to set a URL as another NODE_ENV variable? So that my staging URL can be accessed via for example process.env.NODE_ENV === 'test'?
I would like process.env.NODE_ENV === 'development' to be my local project and process.env.NODE_ENV === 'test' to be my staging URL eg. https://www.stagingsite.com. How would this be set?
Every bootstrap provides their way to do this.
If you are using create-react-app then... try this
https://create-react-app.dev/docs/adding-custom-environment-variables/#what-other-env-files-can-be-used
then create env files after that place script commands and provide file location and name and run build script with appropriate env
"scripts": {
"build": "react-app-env --env-file=config/${BUILD_ENV}.env build",
"build:staging": "BUILD_ENV=staging npm run build",
"build:production": "BUILD_ENV=production npm run build",
...
}
try this for now although react-app-env is deprecated now .. this is code snippetfrom my old project... now cra and dotenv is enough .. although i need to create the flow

electron-builder, how to set node environmental variables

Node.js in windows system can be set environmental before the server is started, like this:
set NODE_ENV=production
That NODE_ENV parameter can be using in node.js or electron by process.env.NODE_ENV.
But when I builder electron by electron-builder, like this:
electron-builder build --windows
How do I set the environmental variables?
Update:
May be cannot pass a fixed environment variable to an executable by electron-builder.
Maybe you can only manually load an environment file, modify it when you package it, or preset the parameters to the dev state. When there is no state, it is production.
If you want an environment variable to be set on runtime you can either set them manually or use other tools like dotenv https://www.npmjs.com/package/dotenv
But the easiest way is to set them at runtime when running the binaries. You can use either a batch script (If windows) for example:
setlocal
set NODE_ENV=production
.\your-binaries.exe
endlocal
Note: setlocal prevents the variable leaking any further.
The one-liner version could be set NODE_ENV=production && .\binaries.exe
Under linux works the same way: set variable then run.
I'm posting this in the hopes that it helps other people in my situation. I have three environments (development, staging, and production), and I wanted my Electron main process to be aware of which environment it was running on.
Now, for development it's quite easy to expose an environment variable to Electron inline using the CLI:
export NODE_ENV=development && electron desktop/main.js
Then, Electron's main process can access this environment variable like so:
const isDev = process.env.NODE_ENV === 'development';
However, being able to distinguish between the staging and production environments was slightly trickier. My staging and production environments are both packaged and deployed using electron-builder, with package.json scripts like so:
"desktop-build": "webpack --config config/webpack/webpack.prod.js && electron-builder --config config/electron.config.js",
"desktop-build-staging": "webpack --config config/webpack/webpack.staging.js && electron-builder --config config/electron.config.js",
NOTE: The webpack configs above expose configs to the renderer process (website), but not the main process.
So my solution to expose the environment to the Electron main process for staging and production was as follows:
Set NODE_ENV=staging or NODE_ENV=production to electron-builder via command line invocation:
# Production
export NODE_ENV=production && webpack --config config/webpack/webpack.prod.js && electron-builder --config config/electron.config.js
# Staging
export NODE_ENV=staging && webpack --config config/webpack/webpack.staging.js && electron-builder --config config/electron.config.js
In my electron.config.js file (configs for electron-builder) use the extraMetadata parameter (docs) to inject a variable into my package.json:
extraMetadata: {
isProduction: Boolean(process.env.NODE_ENV === 'production'),
},
Then you can access that from your Electron main process:
// This variable is injected into package.json by electron-builder via the extraMetadata field (specified in electron.config.js)
const {isProduction} = Boolean(require('./package.json'));

Injecting variables to config.js with Kubernetes

I have a ReactJS application and I'm deploying it using Kubernetes.
I'm trying to wrap my head around how to inject environment variables into my config.js file from within the Kubernetes deployment file.
I currently have these:
config.js file:
export const CLIENT_API_ENDPOINT = {
default:process.env.URL_TO_SERVICE,
};
and here's my Kubernetes deployment variables:
"spec": {
"containers": [
{
"name": "container_name",
"image": "image_name",
"env": [
{
"name": "URL_TO_SERVICE",
"value": "https://www.myurl.com"
}
]
Kinda clueless of why I can't see the environment variable in my config.js file. Any help would be highly appreciated.
Here's my dockerfile:
# Dockerfile (tag: v3)
FROM node:9.3.0
RUN npm install webpack -g
WORKDIR /tmp
COPY package.json /tmp/
RUN npm config set registry http://registry.npmjs.org/ && npm install
WORKDIR /usr/src/app
COPY . /usr/src/app/
RUN cp -a /tmp/node_modules /usr/src/app/
#RUN webpack
ENV NODE_ENV=production
ENV PORT=4000
#CMD [ "/usr/local/bin/node", "./index.js" ]
ENTRYPOINT npm start
EXPOSE 4000
The kubernetes environment variables are available in your container. So you would think the task here is a version of getting server side configuration variables shipped to your client side code.
But, If your react application is running in a container, you are most likely running your javascript build pipeline when you build the docker image. Something like this:
RUN npm run build
# Run app using nodemon
CMD [ "npm", "start" ]
When docker is building your container, the environment variables injected by kubernetes aren't yet yet available. They won't exist until you run the built container on a cluster.
One solution, and this is maybe your shortest path, is to stop building your client side code in the docker file and combine the build and run steps in npm start command . Something like this if you are using webpack:
"start": "webpack -p --progress --config webpack.production.config.js && node index.js"
If you go this route, then you can use any of the well documented techniques for shipping server side environment variables to your client during the build step : Passing environment-dependent variables in webpack. There are similar techniques and tools for all other javascript build tools.
Two: If you are running node, you can continue building your client app in the container, but have the node app write a config.js to the file system on the startup of the node application.
You could do even more complicated things like exposing your config via an api (a variation on the second approach), but this seems like throwing good money after bad.
I wonder if there isn't an easier way. If you have a purely client side app, why not just deploy it as a static site to, say, an amazon or gcloud bucket, firebase, or netlify? This way you just run the build process and deploy to the correct environment. no container needed.

Run Angular + Node.js app in production mode Heroku

So I have an Angular and Node.js app that I'm hosting on Heroku. I want to be able to run this app on localhost for testing but also have it work on Heroku. So I decided to use an environment variable to define the URL of the app for API calls.
So in environment.ts I have
export const environment = {
production: false,
apiURL: 'https://localhost:8080/'
};
And in environment.prod.ts I have:
export const environment = {
production: true,
apiURL: 'myHerokuURL'
};
So when I run on heroku I want the production URL to be used. How can I do this?
To run locally I do, nodemon server.js then ng serve.
However on Heroku I need to do something like ng serve --env=prod but not sure how to do it.
These should help
Option 1
If you are using angular-cli, then
ng build --prod
will do the trick. Then you can copy everything from .dist folder to your server folder
Option 2
you can use http-server to serve your app . To install http-server
npm install http-server -g
and after going to your project folder
http-server ./dist
it will serve all the files in your folder. you can check the terminal what ip-address and port you can use to access the application. Now open up your browser and type
ip-adress:port/index.html
Source: how to deploy angular2 app built using angular-cli
Hope it helps.
In your package.json add
"heroku-postbuild": "ng build --configuration=production"
instead of
"postinstall": "ng build --aot --prod"
This will trigger only one (production) build on heroku. If you leave your current setup you can see in your heroku app logs that you first build everything with --prod but then it just makes normal build.

Where are environment variables stored in node.js?

I want to add some variables to environment variables, but could not find the file which stores these variables.
I checked package.JSon and every folders, but can't find the file storing them.
Where does node.js store it's environment variables?
You can create a .env file in your application folder and define all the environment variables you want to use in the application. Below are sample contents of such a file.
DB_HOST=localhost
DB_USER=root
DB_PASS=123456
Then use the dotenv npm package to import all the variables from the .env file to the node process environment. Then you can access those variables from the process.env object.
require('dotenv').config()
var db = require('db')
db.connect({
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS
})
As pointed in the comments, you have to provide these variables while invoking your node program:
$ NODE_ENV=test node yourApp.js
And you can access this in your code as:
console.log("Environment variable: " + process.env.NODE_ENV);
You can use a package called cross-env .
https://www.npmjs.com/package/cross-env
The issue with using
$ NODE_ENV=test node yourApp.js
is that this wont work in windows systems.
In order to use cross-env you can do the following
npm install --save-dev cross-env
Add the following to your package.json
{
"scripts": {
"dev": "cross-env NODE_ENV=development node index.js"
}
}
You can run your code by running
npm run dev

Resources