If I'm developing the npm package foo
and I want it to be globally installed as a command-line application, I can do this simply by adding to my package.json:
"bin": {
"foo": "./bin/foo.js"
}
Somebody who installs my package globally via npm will have the appropriate batch file and shell script added to their global npm prefix directory. However, suppose I want to be able to launch my package from the shell (or, in the case of Windows, the command prompt). I could do this by creating a batch file/shell script somewhere in one of my PATH directories that simply directly runs my package e.g. @node C:\my\package\directory\bin\foo %*
.
This is a fairly simple and obvious solution, but I felt that npm link
was better suited, as it feels less hacky and is theoretically designed to do this exact thing. I run npm link
in my package directory, then test it by running foo
from the command line. Rather than executing my script, though, foo.js
is actually opened in my default editor. Investigating in the prefix directory, it turns out that the foo.cmd
file (the contents of the foo
shell script are similar) that npm created contains this:
"%~dp0\node_modules\foo\bin\foo.js" %*
Compare with the batch file created by npm install -g
:
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\node_modules\npm\bin\npm-cli.js" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\node_modules\npm\bin\npm-cli.js" %*
)
Why does npm link
produce script files that launch a package's bin file instead of launching node with the bin file as an argument? How can I fix this behavior?
To fix this, use node -v in each project and check the running version of node. Use nvm install x.x.x & nvm use x.x.x to match them up. Afterward, delete your node_modules , delete your package-lock. json , re-run npm i , and re-run npm link in your dependency folder and npm link myDependency in your project folder.
The directory node_modules/.bin is where the binaries of the modules used by your project are stored, normally using symbolic links to the respective binaries in the corresponding module's directory.
It does not change when you cd within a project. npm bin searches the chain of 'ancestor directories' to the cwd for a node_modules directory. This is exactly the desired behavior if you specifically want to use the binaries of modules listed in the project's package.
Path of Global Packages in the system: Global modules are installed in the standard system in root location in system directory /usr/local/lib/node_modules project directory. Command to print the location on your system where all the global modules are installed.
The solution is to add #!/usr/bin/env node
at the beginning of your bin
script. I have no idea why though. I found out by comparing my script to others that worked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With