TLDR: Always prefer npm scripts over direct execution, and local modules over global ones.
JavaScript is not a compiled but an interpreted language. This means you can not run a JavaScript application directly because they are not executable but pass them to an executable runtime, like node.exe on Windows and node on Linux. Runtime takes this source file, processes it and eventually executes it.
So a typical NodeJS application is executed like so:
node my-file.js
You can read more about it here: https://nodejs.org/en/learn/command-line/run-nodejs-scripts-from-the-command-line
Sometimes you may come across a file with shebang at the top. Shebang is a special comment that will be interpreted by the terminal window to pass the provided file to the right executable:
#!/usr/bin/env node
// Rest of the code
You can run a file with shebang directly in your terminal window as if it is an executable:
./my-file.js
Terminal window will pass this file to node
as per instructed by the shebang line.
An actual application usually requires extra parameters, for more flexible and powerful use.
For example a simple greet application may receive a language value to provide localized greetings, greetings in different languages.
node greet.js --lang fr
As you see the complexity keep increasing. NodeJS comes with a package manager to manage Nodejs related tasks. One of these tasks is running Nodejs applications. npm is an executable file that packs several features, running nodejs applications is one of them. It uses package.json
file to set environment values, execution runtime, and receive instruction.
{
scripts: {
greet: "node greet.js",
greetInFr: "node greet.js --lang fr"
}
}
With the scripts property on the package.json file, we can provide predefined arguments.
The following command will run our application with default arguments:
npm run greet
But we don't need to remember how to greet in French, just use the predefined script:
npm run greetInFr
Now, to answer your question. If a npm package provides a cli application, usually it is stored in node_modules/.bin
directory. npm run
command sets the correct paths for those applications. It instantiates a shell and execute the command provided in the package.json file of your project.
So, npm run test
will run this local copy of vitest, and it will receive the run
command with the default values.
Npm also allows you to install applications in a global directory. vitest run
probably runs this global module.
You should prefer npm script over direct execution, and local version to the global one.
pnpm run test
calls the script entry inpackage.json
which runs the copy ofvitest
you have installed in your project'snode_modules
folder.vitest test
will default to using the globalvitest
you have installed if there is one (which, in this case, is perhaps out-of-date?).