I have a package.json with following (simplified) content in the scripts key:
...
scripts: {
"start": "NODE_ENV=${NODE_ENV:=production} node start-app.js",
"poststart": "echo $NODE_ENV"
}
...
From the command line I can run:
npm start
This will run my start-app.js script and set the process.env.NODE_ENV environment variable to "production". See here for syntax explanation.
The poststart will automatically run after start as described here.
However poststart will not "inherit" the NODE_ENV shell environment variable, so the echo command will not echo anything.
My producation code is a little more complex, but what I am trying to accomplish is passing down the NODE_ENV variable from the "starting point" to dependent scripts. Any suggestions/best practices on how to do that?
I dont want to hardcode the NODE_ENV in the poststart, because I might want to do:
NODE_ENV=development npm start
and I want everyting "down the chain" inherit the same environment.
npm_package_node_env
.
export
the variable. export NODE_ENV=something
You have a few options:
better-npm-run,which can define an env for each command separately
Instead of a poststart script, you can concatenate commands for npm like so: "start": "NODE_ENV=${NODE_ENV:=production} node start-app.js && echo $NODE_ENV"
Use a process manager in production like pm2. pm2 lets you define environment specific json files with settings such as NODE_ENV. At our company, we successfully run all of our apps in different environments with pm2 (all the while having the same start command)
this is how I did it, first you need to install two dev-dependencies
https://www.npmjs.com/package/env-cmd this load your env var from your file
https://www.npmjs.com/package/cross-env this use environment variable in script
example scripts:
"env-cmd ./.config/prod.env cross-env-shell \"docker volume create $DOCKER_VOLUME\""
this load $DOCKER_VOLUME env var from prod.env
update: starting from env-cmd version 10, you need specify -f flag if you want to use a custom env file path
"env-cmd -f ./.config/prod.env cross-env-shell \"docker volume create $DOCKER_VOLUME\""
"env-cmd -f ./.env cross-env-shell docker compose build app --build-arg NPM_TOKEN=$NPM_TOKEN"
If you have small use cased, use better-npm-run. For small cases, it works fine. Somehow if you have a lot of commands and it hard manage. Try, batman-cli. Work well and handle lot of environment-dependent issues
npm i -g batman-cli
Success story sharing
cross-env
this is not possible. The second example actually assigns an environment variable (not using cross-env).npm start
command, it works (inside astart
script command).poststart
script.cross-env
also had breaking changes recently.node:8-alpine
Docker container, running Nodejs v8 and NPM v5 and the variables assigned in the container persist. Anyway, I believe we got one misunderstanding: You talk about assigning a variable, if it is not yet assigned, while I understood that it will override previously set variables (NODE_ENV
), right?