Run package.json scripts by NODE_ENV.
Install with npm:
npm install by-node-envInstall with pnpm:
pnpm install by-node-envInstall with Yarn:
yarn add by-node-env- Read
NODE_ENVfromprocess.env. - Read
NODE_ENVfrom .env file. - Defaults
NODE_ENVtodevelopment. - Customize
process.envfor eachNODE_ENV. - Clearer, concise scripts in package.json.
- No more Bash scripting in package.json.
- Works on Linux, macOS, and Windows.
- Compatible with npm, pnpm, and Yarn.
- Consistent workflow for any
NODE_ENV:npm installorpnpm installoryarn install.npm startorpnpm startoryarn start.
When developing a Node.js application in development mode, we often use these different commands: npm run serve, npm run watch, npm run dev, etc. In addition, we also set NODE_ENV=development as an environment variable.
When deploying to production, we often use these different commands: npm start, npm build, npm run prod, etc. NODE_ENV=production is a must-have environment variable in this case.
The package.json might look like this for those situations mentioned above:
{
"scripts": {
"watch": "webpack -d --watch",
"build": "webpack -p",
"dev": "nodemon src",
"prod": "node dist",
"serve": "npm run watch & npm run dev",
"start": "npm build && npm run prod"
}
}Working on multiple projects with different commands can be very confusing and forgetting, especially under heavy cognitive load. As a result, we spend a lot of time consulting the README or the scripts field in package.json.
{
"scripts": {
"build": "by-node-env",
"build:development": "webpack -d --watch",
"build:production": "webpack -p",
"start": "by-node-env",
"start:development": "npm build & nodemon src",
"start:production": "npm build && node dist"
}
}npm build and npm start have long been the de facto commands to build and start a Node.js application, respectively.
Besides that, NODE_ENV should always be explicitly set as an environment variable for best practice. A lot of popular frameworks expect NODE_ENV to be set as well.
Why not combine both, so that when NODE_ENV=production, executing npm start will spawn npm run start:production. Similarly, when NODE_ENV=development, executing npm start will spawn npm run start:development.
Arbitrary NODE_ENV and scripts work too, refer to more examples below.
The priority order of resolving NODE_ENV is as follows:
- Environment variable.
- .env file in project root directory.
development(default).
The .env file, if present, must be located in the root directory of your project, where package.json lie.
The resolved NODE_ENV is available as process.env.NODE_ENV in your application at runtime.
npm start: 1 ➡️ 2aNODE_ENV=development npm start: 1 ➡️ 2aNODE_ENV=production npm start: 1 ➡️ 2b
NODE_ENV=production{
"scripts": {
"start": "by-node-env", // 1
"start:development": "ts-node src", // 2a
"start:production": "ts-node-dev src" // 2b
}
}npm start: 1 ➡️ 2bNODE_ENV=development npm start: 1 ➡️ 2aNODE_ENV=production npm start: 1 ➡️ 2b
{
"scripts": {
// If NODE_ENV is missing, defaults to "development".
"build": "by-node-env",
"build:development": "webpack -d --watch",
"build:production": "webpack -p",
"build:staging": "webpack -p",
// Deployment will not work unless NODE_ENV=production is explicitly set.
"deploy": "by-node-env",
"predeploy:production": "docker build -t ${DOCKER_USER}/${DOCKER_PROJECT} .",
"deploy:production": "docker push ${DOCKER_USER}/${DOCKER_PROJECT}",
// "npm start" is _the_ command to start the server across all environments.
"start": "by-node-env",
"start:development": "npm run build:development",
"prestart:production": "npm run build",
"start:production": "start-cluster build/server/server.js",
"prestart:staging": "npm run build",
"start:staging": "start-cluster build/server/server.js",
// Explicitly set NODE_ENV, which is helpful in CI.
"test": "NODE_ENV=test by-node-env",
"test:test": "mocha"
}
}Encounter bugs or having new suggestions?
Issues, comments, and PRs are always welcomed!
{ "scripts": { "start": "by-node-env", // 1 "start:development": "ts-node src", // 2a "start:production": "ts-node-dev src" // 2b } }