Jiew Meng
Jiew Meng

Reputation: 88189

NPM package.json dependencies and their executables in local vs global

I think npm install|update works when requiring dependencies in source files, but when I want to run an executable, like nodemon, it doesn't appear to work. Is it trying to look for the file globally? How can I make these commands look in node_modules first?


I have a Cakefile that starts the dev server with nodemon. For example:

# **`procExec(procName)`**
# returns the path to executable in `node_`
procExec = (procName) -> 
    console.log "./node_modules/" + procName + "/bin/" + procName
    "./node_modules/.bin/" + procName

# **`cake startdev`**
# Starts the server with `nodemon`
# Watch and compile `.coffee` and `.styl` files in `/client`

task "startdev", "Starts server with nodemon and watch files for changes", ->
    # start nodemon server
    nodemon = spawn procExec("nodemon"), ["server.coffee"]
    processOutput nodemon

    # watch and compile CoffeeScript
    coffee = spawn procExec("coffee"), ["-o", "public/js/app", "-cw", "client/coffee"]
    processOutput coffee

    # watch and compile Stylus
    stylus = spawn procExec("stylus"), ["client/stylus", "-l", "-w", "-o", "public/css/app"]
    processOutput stylus

It works but with a few minor problems:

Upvotes: 0

Views: 2497

Answers (1)

grncdr
grncdr

Reputation: 956

There's a few questions in here, so I'll try and keep them separated.

npm install|update doesn't seem to install nodemon. I think it tries to install globally and fails. I manually did a npm install nodemon separately. Why is this? And how can I tell nodemon to install anyway?

Did you see a warning about "prefer global install"? If that's the case it was just a warning and it would've been installed anyways. If it was a different error please include the output.

Does "./node_modules/.bin/" + procName always resolve to the correct executable?

Yes, any scripts listed in the package.json files of your dependencies will be installed to this folder. However, I much prefer using the npm bin command to always get the correct path.

If you are spawning processes from node, you can also require('npm') and modify process.env.PATH to get the correct node_modules/.bin in place. E.g. at the top of your Cakefile:

npm = require 'npm'
npm.load (err) -> throw err # If config fails to load, bail out early
process.env.PATH = npm.bin + ":" + process.env.PATH
# Now you no longer need to use procExec in your tasks

disclaimer I don't know if modifying PATH like that will work on windows.

Upvotes: 2

Related Questions