Reputation: 312
I've been reading about the .env
file and decided to improve my workflow.
Previously, I used cross-env
to add env-variables right to the npm scripts. example:
"server": "babel-node server.js"
"server:prod": "cross-env NODE_ENV=production babel-node server.js"
And along with that, I had a file with global configs and helpers that contains:
let configs = {}
configs.env = process.env.NODE_ENV || 'development'
configs.devMode = function() {
if(this.env === 'development') return true
}
// Usage:
const url = configs.devMode() ? 'devUrl' : 'prodUrl'
The dotenv
documentation explained almost all my questions.
I know I can create a .env
file and pass variables like:
HOST=localhost
PORT=3000
But, for production, should I write NODE_ENV
in the same file?
Or is there another way to do it?
The change I'm expecting is having one npm script to run the server on both development and production. But, how is my .env
file gonna looks like? And also how to improve my configs
file with the new changes? Should I store the NODE_ENV
in a variable and default it to development
? Or NODE_ENV
will decide the default elsewhere?
Thanks for your help. ^^
Upvotes: 2
Views: 1570
Reputation: 583
This hasn't been commented on or answered for a long time; however, in case anyone is running into this similar problem of migrating from cross-env
to dotenv
, I will try to answer the OP's question here and provide a succinct guide on how to migrate to using dotenv
instead of cross-env
.
First of all, to answer the OP's question, the NODE_ENV
environment variable can still be added to the NPM script in the package.json
like this (make sure that you have both the dotenv
and dotenv-cli
packages installed before changing the script):
dotenv -e .env -v NODE_ENV=production babel-node server.js
Here, the -e
argument supplies which .env
files to use (you can supply multiple by having multiple -e
arguments with the .env
file names), and the -v
argument supplies the environment variable for this specific run/script/command; with -e
arguments, you only provide the file names whereas for -v
arguments, you supply both the key and the value of this variable using KEY=VALUE
syntax as you see in this example.
For more details about the arguments regarding dotenv-cli
, check the doc on the package: https://www.npmjs.com/package/dotenv-cli
To break the command down in this above example, I am telling NPM to run the babel-node
command, executing the server.js
, with the .env
file as one of the environment files that would contain other environment variables (like your HOST
and PORT
variables) and with the NODE_ENV
environment variable set to "production"
, all using the dotenv
command to incorporate the supplied environment variables to the run time of the execution of this command. As long as you have the dotenv
and dotenv-cli
packages both installed as your project's dependencies, these environment variables supplied either by the .env
file under the -e
argument and the variables provided directly by the -v
arguments should register to the current execution of the JavaScript.
On the OP's second question about whether to keep the NODE_ENV
variable in the .env
file or pass it as an argument, I will say that it will depend on the project, but generally, I will say it would be better if you have two separate scripts in your package.json
that passes two different values for the development run and the production run by having the commands like this:
"scripts": {
"server:dev": "dotenv -e .env -v NODE_ENV=development babel-node server.js",
"server:prod": "dotenv -e .env -v NODE_ENV=production babel-node server.js"
}
With these, then you can supply different .env
files for different environments on the fly by having two different .env
files with the corresponding environment name attached to the file name, such as .env.development
and .env.production
.
And then, in your code, you would want to have this (also, simplifying the code posted by the OP as well as some of the codes wouldn't be necessary):
import * as dotenv from "dotenv";
export const getEnv = () => {
dotenv.config({
path: `.env.${process.env.NODE_ENV}`,
});
};
This code snippet above will get the appropriate .env
file based on whether the supplied NODE_ENV
variable from one of the commands in the scripts
section (as shown in the above example) if those environment files exist. For example, you had one environment file, .env.development
, with the environment variables specific to your development environment and ran the server:dev
script via npm run server:dev
(which will run dotenv -e .env -v NODE_ENV=development babel-node server.js
), the NPM will try to grab and inject the environment variables and their values from the .env.development
file to the current run time of the current execution. The same can be said about running your program in the production environment.
More on this here: https://www.npmjs.com/package/dotenv
With that in mind, to use the environment variables, you would just have this in your code:
// Usage
const url = `http://${process.env.HOST}:${process.env.PORT}`
Based on the environment variables found in the environment files you've supplied, it will use the appropriate HOST
and PORT
values; however, note that this would only work if you have two different environment files for two different environments, namely development
and production
environments, and have different HOST
and PORT
variable values, like this:
.env.development
:
HOST=localhost
PORT=3000
.env.production
:
HOST=https://some-actual-address.com
PORT=8080
With that being said, generally, you would have the .env
file (without the environment name attached to it) for sensitive values like the API token that would be necessary for both environments (which you wouldn't usually push to the repo):
.env
:
API_TOKEN=*************
A lot of projects I've worked with so far usually had maybe 2 or 3 environment files (.env
files): one for the development environment, one for the production, and a common one for all environments. Note that any of these .env
files shouldn't have any sensitive information/values if they are being pushed to the repo, as having any credentials or API token in the .env
file in the repo would be a security risk.
I hope this helps.
Upvotes: 0