26

I would like to use $>npm start and have it use "nodemon" for development and "node" for production. I can't put conditional logic in my package.json file, so how is this best accomplished?

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • * well of course you can put conditional logic in package.json scripts lines. These script string values are simple interpreted by bash. – Alexander Mills Jun 20 '17 at 07:49
  • Why would you put `npm` into something running in production? It's an overhead you really don't need. – kaiser Mar 27 '21 at 21:16

4 Answers4

21

You should be able to use NPM's start as a regular shell script.

"scripts": {
  "start": "if [$NODE_ENV == 'production']; then node app.js; else nodemon app.js; fi"
}

Now to start your server for production

$ NODE_ENV='production' npm start

or for development

$ NODE_ENV='development' npm start
Daniel
  • 38,041
  • 11
  • 92
  • 73
  • cool - when i tried just the shell script embedded in the package.json file, I got an error, but looks like the commands after that will help. i am using heroku so i believe i have to set the env variable on heroku – Alexander Mills Nov 14 '14 at 08:14
  • 2
    this doesn't work for Windows, but it probably works for Mac/Unix – Alexander Mills Dec 20 '14 at 00:32
  • This threw error `[: development: unexpected operator` for me. I had to do this instead `if [$NODE_ENV = 'production']; then node app.js; else nodemon app.js; fi`. See https://stackoverflow.com/a/18102991/100466 for context. – Waseem Mar 25 '19 at 11:11
  • Rather than having `$ NODE_ENV='development' npm start`, why not just create another script `"dev":"nodemon app.js"` and have `npm run dev`. – Fandi Susanto Jun 06 '19 at 09:51
11

nodemon actually reads the package.start value, so if you just set the start property to what you'd have in production, like node app.js, then run nodemon without any arguments, it'll run with package.start and restart as you'd expect in development.

Remy Sharp
  • 4,520
  • 3
  • 23
  • 40
  • 2
    While this is useful when you are just using nodemon globally, I think it doesn't help for the case when you want to type `npm start` and have it run nodemon if in the `dev` environment and node when in `production`. The answer below with the conditional if statement seems to be the only way to accomplish that. – Adam Reis Aug 29 '16 at 19:17
  • 1
    @AdamReis: Somtimes a question asks for how to do a wrong thing. This is known as the XY problem and it is not only acceptable but encouraged on SO to answer with the correct way of achieving Y without doing X. In this case the OP may be unaware of how nodemon actually works and so is asking for something that is not necessary. So it is not necessary to accomplish the literal question if there is a better way to do things. – slebetman Jan 04 '17 at 16:39
7

I liked Daniel's solution, but thought it would be even cleaner to put it in a separate file, startup.sh:

#!/bin/sh

if [ "$NODE_ENV" = "production" ]; then
  node src/index.js;
else
  nodemon src/index.js;
fi

Then just change package.json to read:

"scripts": {
  "start": "../startup.sh"
},
Rich Churcher
  • 7,361
  • 3
  • 37
  • 60
Erfa
  • 643
  • 6
  • 9
  • 1
    I'm just curious, why did you use `node` for production instead of `nodemon`. Thanks. – Woppi Jul 02 '18 at 06:13
  • Because Nodemon automatically restarts the server on anycode change which is inconvenient in production if an accedent happens or something changes a file and makes an error. If node is used for production you would have to restart to reflect the changes – isethi Apr 07 '19 at 03:15
7

Instead of putting logic in your "start", just add another script like "start-dev":"nodemon app.js" and execute it like "npm run-script start-dev".

Yash Ranjan
  • 75
  • 1
  • 3