39

I have 2 main build configurations - dev and prod. I push updates to a heroku server that run npm install --production to install my app. In the package.json I have the following segment:

"scripts": {
    "postinstall": "make install"
}

that runs a make file that is responsible for uglifying the code and some other minor things.

However, I don't need to run this makefile in development mode. Is there any way to conditionally run scripts with npm?..

Thanks!

4 Answers 4

71

You can have something like this defined in your package.json (I'm sure theres a better shorthand for the if statement.)

"scripts": {
    "postinstall":"if test \"$NODE_ENV\" = \"production\" ; then make install ; fi "
}

Then when you execute npm with production flag like you stated you already do

npm install --production

it will execute your make install because it will set $NODE_ENV = production


When I need to conditionally execute some task(s), I pass environment variables to the script/program and which takes care of that logic. I execute my scripts like this

NODE_ENV=dev npm run build

and in package.json, you would start a script/program

"scripts": {
    "build":"node runner.js"
}

which would check the value of the environment variable to determine what to do. In runner.js I do something like the following

if (process.env.NODE_ENV){
  switch(process.env.NODE_ENV){
    ....
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

As you note, can also do the conditional a bit more succinctly: "postinstall": "if [ test = \"production\" ]; then make install; fi"
is that cross platform?
@SuperUberDuper no it would not be compatible with windows dos. It would have to be adjusted accordingly to the platform the npm script is to run on. DOS has conditionals as well.
Hi, James, where is the documentation for this conditionally task because i can't find them, i need to do something like this "postinstall":"if test \"$NODE_ENV\" = \"production\" ; then --env=prod ; else --env=qa fi " where i choose between prod and qa
@Milo the conditional is just bash conditional expression.
|
20

For conditional npm scripts, you can use cross-platform basic logical operators to create if-like statements ( || and && ). I've run into needing to run scripts to only generate helpers once on any machine. You can use inline javascript to do this by using process.exit() codes.

"scripts": {
    "build":"(node -e \"if (! require('fs').existsSync('./bin/helpers')){process.exit(1)} \" || npm run setup-helpers) && npm run final-build-step"
}

So for testing envs you might do:

"scripts": {
    "build":"node -e \"if (process.env.NODE_ENV === 'production'){process.exit(1)} \" || make install"
}

5 Comments

This is the only solution that worked cross platform for me; it should have been selected as the correct answer.
You get my vote because of cross platform support.
While ugly and kind of stupid, this indeed is the best thing I could find after searching for a while. I do wonder though, surely there is some npm package that makes this cleaner.
Any npm package providing anything like an IIF cli will quickly devolve into similar levels of complexity in your script strings, and will similarly suffer from the nightmare that is the double-encoding of nested strings. Personally, if I have more than one of these, I create a simple JS file with a switch statement on the first arg, so I can have all my tests in one file, and still leave the && and || in the script strings.
In my case, I have a script in package.json with a half-dozen commands separated with &&. One of the middle commands is a call to node to run a .js file. If that .js file gets an error I end the error handler with process.exit(1); That prevents the next command in my package.json script from running.
1

Can't you add another section in your .json under devDependencies? Then if you do npm install it'd install the packages specified under devDependincies and npm install --production would install the regular dependcies.

Comments

0

I would encourage you to take a different tack on uglifying your code. Take a look at connect-browserify or the even more powerful asset-rack.

These can automatically uglify your code on launch of the Express server, rather than on install. And you can configure them to do different things in development and production.

2 Comments

From the connect-browserify github page: You should never use this middleware in production — use nginx for serving pre-built bundles to a browser.
Thanks for that correction. Asset Rack is very much designed for use in production, however.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.