NODE_ENV variable in Node.js - node.js

I am a beginner in Node and I see the following code in my project:
process.env.NODE_ENV
What is NODE_ENV and how can I get access to it or change it? It seems to pick up some values but don't know from where is it getting picked up.
Please let me know.

NODE_ENV is the name of an environment variable, and you can access and change it in your shell Ex: export NODE_ENV=development , you can change it when running your process, Ex: NODE_ENV=production node application.js, or you can change it in one of your shell's configuration files.

Related

react-native unable to assign Production for NODE_ENV variable

I am trying to utilise the process.env.NODE_ENV to switch between the environments for my react native app, and am facing two issues here
1. Assigning parameter to NODE_ENV doesn't seem to change the env value straight forward,
executing the below command shows that it changed process.env.NODE_ENV value but doesnt seem to have changed the global.process.env.NODE_ENV
execution command:
NODE_ENV=development npm start -- --reset-cache
output: Please note, the second log statement still prints out development.
console.log("printing the changed value - ", process.env.NODE_ENV); // --> printing the changed value - production
console.log("checking the env content - ", process.env); // ---> checking the env content - { NODE_ENV: 'development' }
Workaround that i tried is to assign the process.env.NODE_ENV to the global instance,
global.process.env.NODE_ENV = process.env.NODE_ENV
Please do advise if this is a good approach to proceed with.
2. Assigning "Production" as a value to NODE_ENV throws Attempted to Assign to read only property error,
Execution Command:
NODE_ENV=production npm start -- --reset-cache
Please find image attached -
AssignToReadOnlyPropertyIssue
The problem your facing here comes from an erroneous assumption:
react-native doesn't execute javascript in the same way as node.
Let's consider the following npm script:
"scripts": {
"start": "node index.js"
}
When running SOME_VAR="some value" npm start, process.env will contain a entry for that environment variable, since it is running from the process where SOME_VAR was defined.
In react-native something different happens:
calling npm start starts the react-native packager which bundles your javascript code and then sends that javascript bundle to the installation in your emulator or device, where the bundle is in its turn executed. react-native's packager doesn't "forward" the environment variables defined where the javascript was bundled.
Hopefully there are packages that aid us to be able to keep using the same patterns we're used to using when developing node apps.
One I found really helpful was babel-plugin-transform-inline-environment-variables. This is a babel plugin that transforms process.env.SOME_VAR type calls to the value of SOME_VAR during bundle time.
The only headache I had with it was that when I was first trying to see how it worked I was changing the environment variables, but it only seemed to work "randomly". Turns out I was a victim of webpack's cache. If there are no changes in the code it is watching it won't update the bundle. I then learned I had to be aware of that

how to configure express js application according to environment? like development, staging and production?

I am new to expressjs app development, now need to configure application as per environment. came across 'node-env-file' , 'cross-env'. but hardly understood anything. Pls suggest how to set env variables as per environment or some good documentation suggestions pls?
Based on environment, I would like to load my configuraiton file.As of now, I have two config files, one for dev and one for production.
The idea is to set NODE_ENV as the environmental variable to determine whether the given environment is production or staging or development. The code base will run based on this set variable.
The variable needs to set in .bash_profile
$ echo export NODE_ENV=production >> ~/.bash_profile
$ source ~/.bash_profile
For more, check Running Express.js in Production Mode
I follow Ghost.org (a Node.js production) app's model.
Setting environments
Once that is done, you can have the environmental details in respective json files like config.production.json, config.development.json
Next, you need to load one of these file based on the environment.
var env = process.env.NODE_ENV || 'development';
var Nconf = require('nconf'),
nconf = new Nconf.Provider(),
nconf.file('ghost3', __dirname + '/env/config.' + env + '.json');
For more on how Ghost does this, check config/index.js
I use a .env file with env vars:
VAR=VALUE
And read that with source command before running express
$ source .env
$ node app.js
Then, to access inside express, you can use:
var temp = process.env.VAR; //contains VALUE
You can use dotenv module, to automatically load .env file

Node JS, detect production environment

When I'm in dev mode I don't want my server to send email and some other stuff so I have this in server.js file:
process.env.NODE_ENV = 'development';
When I move it to production i change the value to 'production'.
Problem is of course that it is easy to forget on deployments. Is it possible somehow to detect when server is in production?
If it's not, is it possible to write a batch script that replaces a string in a file?
You shouldn't manually change values of process.env object, because this object is reflecting your execution environment.
In your code you should do the following:
const environment = process.env.NODE_ENV || 'development';
And then you launch your app in production like this:
$ NODE_ENV=production node app.js
If NODE_ENV environment variable is not set, then it will be set to development by default.
You could also use dotenv module in development to specify all environment variables in a file.
Furthermore, I've implemented a reusable module, which allows to automatically detect environment by analyzing both CLI arguments and NODE_ENV variable. This could be useful on your development machine, because you can easily change environment by passing a CLI argument to you Node.js program like this: $ node app.js --prod. It's also nice to use with Gulp: $ gulp build --prod.
Please see more details and use cases on the detect-environment's page.
The suggested way to tackle these kind of problems is by using the process global object provided by NodeJS. For example:
var env = process.env.NODE_ENV || "development";
By the above line. We can easily switch between development / production environment. If we haven't configured any environment variable it works with development environment.
process.env is an object that contains the user environment.
For example if we are running our application in a bash shell and have configured NODE_ENV to production. Then i can access that in node application as process.env.NODE_ENV.
There are multiple ways to define this NODE_ENV variable for nodejs applications:
## Setting environment variable for bash shell
export NODE_ENV=production
## Defined while starting the application
NODE_ENV=production node app.js
So i don't think you would require any batch file for this. When handling multiple configuration variables, follow this.
This is normally handled through configuration files (e.g. config frameworks like node-convict) and through environmental variables. In the start command in production, you might do something like:
NODE_ENV=production npm start
then the process.env.NODE_ENV would be properly set by any module in your app that cares.

Workaround for NODE_ENV during build

I'm having a problem with a NPM post-install script, the issue is that the build process ignores the configured NODE_ENV (set via cctrlapp x/y config.add) and always defaults to production. For what I've seen this was "resolved" two months ago by Heroku. From this issue, it seems that it should be transparent.
Is there something I must do to have access to my ENV variables during the build? Any workaround?
Thanks!
I found a workaround, from the different ENV vars the only one with a value during the build is DEP_NAME, but it's enough since we can extract the env from it: project/environment. This works in CloudControl, no idea if it would work in Heroku.
if ('DEP_NAME' in process.env) {
process.env.NODE_ENV = process.env.DEP_NAME.split('/')[1];
}

Setting Environment Variables for Node to retrieve

I'm trying to follow a tutorial and it says:
There are a few ways to load credentials.
Loaded from environment variables,
Loaded from a JSON file on disk,
The keys need to be as follows:
USER_ID, USER_KEY
...This means that if you properly set your environment variables, you
do not need to manage credentials in your application at all.
Based on some Googling, it appears that I need to set the variables in process.env? How and where do I set these credentials? Example Please.
Environment variables (in this case) are being used to pass credentials to your application. USER_ID and USER_KEY can both be accessed from process.env.USER_ID and process.env.USER_KEY respectively. You don't need to edit them, just access their contents.
It looks like they are simply giving you the choice between loading your USER_ID and USER_KEY from either process.env or some specificed file on disk.
Now, the magic happens when you run the application.
USER_ID=239482 USER_KEY=foobar node app.js
That will pass the user id 239482 and the user key as foobar. This is suitable for testing, however for production, you will probably be configuring some bash scripts to export variables.
I highly recommend looking into the dotenv package.
https://github.com/motdotla/dotenv
It's kind of similar to the library suggested within the answer from #Benxamin, but it's a lot cleaner and doesn't require any bash scripts. Also worth noting that the code base is popular and well maintained.
Basically you need a .env file (which I highly recommend be ignored from your git/mercurial/etc):
FOO=bar
BAZ=bob
Then in your application entry file put the following line in as early as possible:
require('dotenv').config();
Boom. Done. 'process.env' will now contain the variables above:
console.log(process.env.FOO);
// bar
The '.env' file isn't required so you don't need to worry about your app falling over in it's absence.
You can set the environment variable through process global variable as follows:
process.env['NODE_ENV'] = 'production';
Works in all platforms.
Just provide the env values on command line
USER_ID='abc' USER_KEY='def' node app.js
If you want a management option, try the envs npm package. It returns environment values if they are set. Otherwise, you can specify a default value that is stored in a global defaults object variable if it is not in your environment.
Using .env ("dot ee-en-vee") or environment files is good for many reasons. Individuals may manage their own configs. You can deploy different environments (dev, stage, prod) to cloud services with their own environment settings. And you can set sensible defaults.
Inside your .env file each line is an entry, like this example:
NODE_ENV=development
API_URL=http://api.domain.com
TRANSLATION_API_URL=/translations/
GA_UA=987654321-0
NEW_RELIC_KEY=hi-mom
SOME_TOKEN=asdfasdfasdf
SOME_OTHER_TOKEN=zxcvzxcvzxcv
You should not include the .env in your version control repository (add it to your .gitignore file).
To get variables from the .env file into your environment, you can use a bash script to do the equivalent of export NODE_ENV=development right before you start your application.
#!/bin/bash
while read line; do export "$line";
done <source .env
Then this goes in your application javascript:
var envs = require('envs');
// If NODE_ENV is not set,
// then this application will assume it's prod by default.
app.set('environment', envs('NODE_ENV', 'production'));
// Usage examples:
app.set('ga_account', envs('GA_UA'));
app.set('nr_browser_key', envs('NEW_RELIC_BROWSER_KEY'));
app.set('other', envs('SOME_OTHER_TOKEN));
It depends on your operating system and your shell
On linux with the shell bash, you create environment variables like this(in the console):
export FOO=bar
For more information on environment variables on ubuntu (for example):
Environment variables on ubuntu
Windows-users: beware! These commands are recommended for Unix. But on Windows they don't persist, they only set a variable in your current shell, and it'll be gone when you restart.
SET TEST="hello world"
$env:TEST = "hello world"
3 ways to set a persistent environment variable on Windows:
A) .env file in your project - The best method. As you can just copy that file to any computer and get the same config when running the project.
Create an .env file in your project folder root with the content: TEST="hello world"
Write some node code that will read that file. I suggest installing dotenv ( npm install dotenv --save) and then add require('dotenv').config(); during your node setup code.
process.env.TEST is now usable in node
Env-files are a good way of keeping api-keys out of your codebase
B) Use Powershell - this will create a variable that will be accessible in other terminals. But it sucks as it'll be lost after you restart your computer.
[Environment]::SetEnvironmentVariable("TEST", "hello world", "User")
This method is widely recommended on Windows forums, people seem unaware it doesn't persist after a system restart....
C) Use the Windows GUI
Search for "Environment Variables" in the Start Menu Search or in the Control Panel, Select "Edit the system environment variables". A dialogue opens and you click the button "Environment Variables" at the bottom of the dialogue to open an edit-view where you can click the "New" button to add a new environment variable. Easy. And persists even after a restart. But not something you should use to config a specific codebase.
Like ctrlplusb said, I recommend you to use the package dotenv, but another way to do this is creating a js file and requiring it on the first line of your app server.
env.js:
process.env.VAR1="foo"
process.env.VAR2="bar"
app.js:
require('./env') // env.js relative path.
console.log(process.env.VAR1) // foo
Step 1: Add your environment variables to their appropriate file. For example, your staging environment could be called .env.staging, which contains the environment variables USER_ID and USER_KEY, specific to your staging environment.
Step 2: In your package.json file, add the following:
"scripts": {
"build": "sh -ac '. ./.env.${REACT_APP_ENV}; react-scripts build'",
"build:staging": "REACT_APP_ENV=staging npm run build",
"build:production": "REACT_APP_ENV=production npm run build",
...
}
then call it in your deploy script like this:
npm run build:staging
Super simple set up and works like a charm!
Source: https://medium.com/#tacomanator/environments-with-create-react-app-7b645312c09d
Make your life easier with dotenv-webpack. Simply install it npm install dotenv-webpack --save-dev, then create an .env file in your application's root (remember to add this to .gitignore before you git push). Open this file, and set some environmental variables there, like for example:
ENV_VAR_1=1234
ENV_VAR_2=abcd
ENV_VAR_3=1234abcd
Now, in your webpack config add:
const Dotenv = require('dotenv-webpack');
const webpackConfig = {
node: { global: true, fs: 'empty' }, // Fix: "Uncaught ReferenceError: global is not defined", and "Can't resolve 'fs'".
output: {
libraryTarget: 'umd' // Fix: "Uncaught ReferenceError: exports is not defined".
},
plugins: [new Dotenv()]
};
module.exports = webpackConfig; // Export all custom Webpack configs.
Only const Dotenv = require('dotenv-webpack');, plugins: [new Dotenv()], and of course module.exports = webpackConfig; // Export all custom Webpack configs. are required. However, in some scenarios you might get some errors. For these you have the solution as well implying how you can fix certain error.
Now, wherever you want you can simply use process.env.ENV_VAR_1, process.env.ENV_VAR_2, process.env.ENV_VAR_3 in your application.
For windows users this Stack Overflow question and top answer is quite useful on how to set environement variables via the command line
How can i set NODE_ENV=production in Windows?
Came across a nice tool for doing this.
node-env-file
Parses and loads environment files (containing ENV variable exports) into Node.js environment, i.e. process.env - Uses this style:
.env
# some env variables
FOO=foo1
BAR=bar1
BAZ=1
QUX=
# QUUX=
If you are using a mac/linux and you want to retrieve local parameters to the machine you're using, this is what you'll do:
In terminal run nano ~/.bash_profile
add a line like: export MY_VAR=var
save & run source ~/.bash_profile
in node use like: console.log(process.env.MY_VAR);
As expansion of #ctrlplusb answer,
I would suggest you to also take a look to the env-dot-prop package.
It allows you to set/get properties from process.env using a dot-path.
Let's assume that your process.env contains the following:
process.env = {
FOO_BAR: 'baz'
'FOO_🦄': '42'
}
Then you can manipulate the environment variables like that:
const envDotProp = require('env-dot-prop');
console.log(process.env);
//=> {FOO_BAR: 'baz', 'FOO_🦄': '42'}
envDotProp.get('foo');
//=> {bar: 'baz', '🦄': '42'}
envDotProp.get('foo.🦄');
//=> '42'
envDotProp.get('foo.🦄', {parse: true});
//=> 42
envDotProp.set('baz.foo', 'bar');
envDotProp.get('', {parse: true});
//=> {foo: {bar: 'baz', '🦄': 42}, baz: {foo: 'bar'}}
console.log(process.env);
//=> {FOO_BAR: 'baz', 'FOO_🦄': '42', BAZ_FOO: 'bar'}
envDotProp.delete('foo');
envDotProp.get('');
//=> {baz: {foo: 'bar'}}
console.log(process.env);
//=> {BAZ_FOO: 'bar'}
This helps you to parse the environment variables and use them as a config object in your app.
It also helps you implement a 12-factor configuration.
A very good way of doing environment variables I have successfully used is below:
A. Have different config files:
dev.js // this has all environment variables for development only
The file contains:
module.exports = {
ENV: 'dev',
someEnvKey1 : 'some DEV Value1',
someEnvKey2 : 'some DEV Value2'
};
stage.js // this has all environment variables for development only
..
qa.js // this has all environment variables for qa testing only
The file contains:
module.exports = {
ENV: 'dev',
someEnvKey1 : 'some QA Value1',
someEnvKey2 : 'some QA Value2'
};
NOTE: the values are changing with the environment, mostly, but keys remain same.
you can have more
z__prod.js // this has all environment variables for production/live only
NOTE: This file is never bundled for deployment
Put all these config files in /config/ folder
<projectRoot>/config/dev.js
<projectRoot>/config/qa.js
<projectRoot>/config/z__prod.js
<projectRoot>/setenv.js
<projectRoot>/setenv.bat
<projectRoot>/setenv.sh
NOTE: The name of prod is different than others, as it would not be used by all.
B. Set the OS/ Lambda/ AzureFunction/ GoogleCloudFunction environment variables from config file
Now ideally, these config variables in file, should go as OS environment variables (or, LAMBDA function variables, or, Azure function variables, Google Cloud Functions, etc.)
so, we write automation in Windows OS (or other)
Assume we write 'setenv' bat file, which takes one argument that is environment that we want to set
Now run "setenv dev"
a) This takes the input from the passed argument variable ('dev' for now)
b) read the corresponding file ('config\dev.js')
c) sets the environment variables in Windows OS (or other)
For example,
The setenv.bat contents might be:
node setenv.js
The setenv.js contents might be:
// import "process.env.ENV".js file (dev.js example)
// loop the imported file contents
// set the environment variables in Windows OS (or, Lambda, etc.)
That's all, your environment is ready for use.
When you do 'setenv qa', all qa environment variables will be ready for use from qa.js, and ready for use by same program (which always asks for process.env.someEnvKey1, but the value it gets is qa one).
Hope that helps.
Pretty much like some others answers but without any lib nor (bash) export.
I have some encrypted variables then I need to generate them on the fly.
The magic happens with set -a && ... && set +a which can be some content or a file.
#!/bin/sh
set -a
SOMEVAR_A="abcd"
SOMEVAR_B="efgh"
SOMEVAR_C=123456
set +a
# or
set -a && . ./file && set +a
I have a docker-entrypoint.sh with:
#!/bin/sh
node app/config/set-environment.js
ENVFILE=/tmp/.env
if [[ ! -f "$ENVFILE" ]] ; then
echo "File $ENVFILE is not there, aborting."
exit
fi
# here is where things happen
set -a && . $ENVFILE && set +a
if [ "${NODE_ENV}" = "development" ]; then
npx nodemon app/server.js
else
node app/server.js
fi
exec "$#"
While set-environment.js generates a (tmp) .env file
I was getting undefined after setting a system env var. When I put APP_VERSION in the User env var, then I can display the value from node via process.env.APP_VERSION
in case you're using visual studio code debugging feature, you can add "envFile": "${workspaceRoot}/.env" to launch configuration. This way you don't have to use dotenv.
{
"cwd": "${workspaceRoot}",
"command": "npm start",
"name": "Run be",
"request": "launch",
"type": "node-terminal",
"envFile": "${workspaceRoot}/.env"
},
Make a file called local-env and populate it with variables
PORT=80
DB_NAME=foo
SOME_URL=example.com
Now run node thusly:
source ./local_env ; node index.js
Use cross-env. It will save you a lot of headache
npm i -S cross-env
cross-env PARAM=value node ./index.js
That's usually good for non-credentials. For things like credentials and keys
it's better not to store hardcoded user id and password but use .env file which is not in repo and dotenv

Resources