Merits of using npm over shell program(Bash) - bash

I have recently started using npm (https://www.npmjs.com) and it's wonderful that we can use npm as build tool. But after digging much, I got question in my mind.
As a building tool, npm is almost like shell program(sh or bash), because we just execute shell commands in npm package.json file. And even sometimes we execute shell program from it.
EDIT: here is an example how I use it.
package.json
{
"name": "myproject",
"devDependencies": {
"jshint": "latest",
"minify": "latest",
"mocha": "latest"
},
"scripts": {
"lint": "jshint **.js",
"test": "mocha test/",
"minify":"minify *.js",
"build":"npm run lint && npm run test && npm run minify"
}
}
So, everything we're doing with npm bundling facility, we can achieve by writing normal shell program(sh or bash). I want to know what are special advantages of npm over nprmal shell program. What we can't do with shell script, which we can achieve with npm as build tool.
There must be some special vision behind developing tool. Otherwise everything we can do with shell program (Makefile).
Your answer will be appreciated.
Thanking in advance!

Npm as a build tool: do you mean the npm scripts feature? Or something like Grunt or Gulp?
Npm itself is just a package ecosystem for JavaScript (Node) packages. Shell is, well, shell. You can create shell programs with anything which can be run using a shell (Bash, C, Python, PHP, and so on). I presume you mean shell languages like sh or bash in your question.
If you develop Node or browser applications, or use a tool such as Gulp, Grunt, Fly, npm scripts and so on then npm is a good (mandatory) pick.
If you need to create build procedures for something really custom or lower level than regular applications, then custom shell builders or maybe Makefiles could be a better fit. Though some people seem to use Makefiles in places where npm and a build tool like Gulp would be a simpler choice.
What are you building with npm right now which got you questioning the usage of it?

Related

'NODE_OPTIONS' is not recognized as an internal or external command - still an issue

I am following the guide from here on a nextjs application. Using VSCode on windows.
It says use the script:
"dev": "NODE_OPTIONS='--inspect' next dev"
this results in:
'NODE_OPTIONS' is not recognized as an internal or external command,
operable program or batch file.
Yes I know there is already a question with the same name but it is 2.5 years old, has 8k views and no accepted answer. I am unable to comment to add information to it. Feel free to mark this as a duplicate but please at least link it in a comment in the other question.
The one answer that is there advises installing yet another (maintenance mode) dependency and configuring it to change environment variables.
This and other research leads me to believe that there is an issue with environment variables here. Can't I just set them manually? Why is this not mentioned in the official next guide? How can I set the correct environment variable?
There is a way to get it working and you can find a similar question posted here.
Step 1
npm i cross-env --save-dev
Step 2
Edit your package.json so the dev option looks like this
{
"scripts": {
"dev": "cross-env NODE_OPTIONS='--inspect' next dev",
"build": "next build",
"start": "next start"
}
}
Step 3
You can now launch your NextJS program in a separate terminal. After that follow the NextJS VSCode debugging instructions. Attach VSCode to the running NextJS instance.
You're all set.
Maybe this can help us
Debugging on Windows
Windows users may run into an issue when using NODE_OPTIONS='--inspect' as that syntax is not supported on Windows platforms. To get around this, install the cross-env package as a development dependency (--dev with NPM or -D for Yarn) and replace the dev script with the following.
"dev": "cross-env NODE_OPTIONS='--inspect' next dev",
cross-env will set the NODE_OPTIONS environment variable regardless of which platform you are on (including Mac, Linux, and Windows) and allow you to debug consistently across devices and operating systems.

How to run a shell script from my published npm package

I realize this is kind of a silly question, but I'm deeply curious about how I accomplish the following.
I created a shell script for my cohort at school which builds out large project templates. I've successfully published the package to npm, but after downloading, I can't get the script to run. I'd like for users to simply download the package and run something like $ npm project-template start(as an example) to trigger the script.
Is this possible?
If anyone has advice, suggestions, pointers, I'd really appreciate it. Thanks in advance!
Its always after I ask the internet for answers that I find the answers on my own.
Add the program to the binaries object
Basically, what I needed to do was to add the command I wanted to run to the bin section of the package.json:
"bin": {
"nameOfCommand": "path/to/script.sh"
}
The left side, nameOfCommand, is the name of the command that is used in your terminal
$ nameOfCommand args --options
The right side is the path to your CLI program, in this case, a bash/shell script.
The information can be found here in this article by NPM.

What is a Makefile? And how is it different from a Gruntfile or npm run?

Recently, while getting acquainted with the Mocha javascript testing framework, I came across this section that I didn't understand:
Makefiles
Be kind and don't make developers hunt around in your docs to figure
out how to run the tests, add a make test target to your Makefile:
test:
./node_modules/.bin/mocha --reporter list
.PHONY: test
Which is hardly descriptive, and not very helpful if you don't know what a makefile is.
So, What is a Makefile? And how is it different from a Gruntfile or using npm run?
Makefile
A Makefile (usually with no file extension) is a configuration file used by the Unix make tool.
Quoted from one of the best introductions I have found on Make that I highly recommend you read if you are interested in knowing more about make specifically, and task-runners in general.
Make is the original UNIX build tool. It existed a long time before
gulp, or grunt. Loved by some, loathed by others it is at least worth
being aware of how make works, what the strengths are and where it
falls short.
Make is available on UNIX-like systems. That means OSX, BSD and Linux.
It exposes any system command meaning that you can run system commands
and execute arbitrary scripts. There is no doubt that tools like gulp
and grunt are inpsired by or at least a reaction to make.
To use make you create a Makefile and then run make [what to run] from
the terminal.
Gruntfile.js
A Gruntfile.js is a javascript configuration file used by the Grunt.js tool.
The newer node.js version of make, if you will, is Grunt.js which is cross-platform (works on Windows) and written in Javascript. Both can do similar things like concatenate files, minify css, run tests, etc. and there is a lot of information on the web about Grunt.
'npm run'
Another option that some developers prefer to use is npm itself, using the npm run command as described in this informative post on how to use npm run for running tasks:
There are some fancy tools [Grunt] for doing build automation on javascript
projects that I've never felt the appeal of because the lesser-known
npm run command has been perfectly adequate for everything I've needed
to do while maintaining a very tiny configuration footprint.
If you haven't seen it before, npm looks at a field called scripts in
the package.json of a project in order to make things like npm test
from the scripts.test field and npm start from the scripts.start field
work.
npm test and npm start are just shortcuts for npm run test and npm run
start and you can use npm run to run whichever entries in the scripts
field you want!
Other good introductory resources:
Introduction to grunt.js and npm scripts, and choosing between the
two.
Cross platform JavaScript.
Package Managers: An Introductory Guide For The Uninitiated Front-End
Developer.

Configure node npm package.json so that "npm test" works on both unix and windows

I have developed a node.js npm module, developing under Windows. Today I wrote some Mocha tests. After many struggles, it seemed that for npm test to work, package.json had to look like this: (there may be other options???)
"scripts": { "test": "node node_modules/mocha/bin/mocha" }
instead of what's in all the Unix based books,
"scripts": { "test": "./node_modules/.bin/mocha" }
How can I set package.json up to work on both Windows and Unix? I'm assuming that Travis-CI runs Unix, so, should I link the build to that, it will blow up with the Windows version.
I found a two year old thread where somebody requested a feature for exactly this. That thread seemed to die out. This SO question seems to be close, but it isn't exactly what I want and, frankly, I can't understand the answer. :-( Can anybody clarify?
For the time being, I am going
"scripts": {
"test": "node node_modules/mocha/bin/mocha",
"testOnUnixUseThis" : "./node_modules/.bin/mocha (I think)",
"testOnWindowsUseThis" : "node node_modules/mocha/bin/mocha"
},
Unfortunately, you cant go npm test testOnWindowsUseThis or npm testOnWindowsUseThis. And it doesn't fix the Travis-CI issue. But at least a person who downloads the module can (hopefully) see what is going on.
Any better ideas? Am I the only person still developing under Windows??? :-)
I've always been able to npm install -g mocha or npm install mocha and then just add
"scripts": {
"test": "mocha spec"
}
to package.json. That may or may not work in EVERY environment. I know, for instance, with lineman, you have to use bin/mocha. Also, if you don't find a way around this, set your test script up for Unix and then add a second script called "wintest" or something that does whatever you need it to do in Windows. You can name your scripts whatever you want. The default ones (test, start, etc.) can be used with npm [command]; any non-standard ones (like wintest) can be used with npm run-script [command], and they will still work.
A little back story on how/why this works:
When you install a module globally, it's available on PATH (or whatever the windows equivalent is). When you install a project dependency, if that module has any binaries, those are symlinked to node_modules/.bin and when you run npm run [some-command], npm helpfully adds node_modules/.bin to PATH for that command. So when mocha is installed globally "test": "mocha spec" uses your globally installed mocha to run tests. When it's a project dependency, it uses the one in node_modules/.bin. The one gotcha I've found with this is that npm adds node_modules/.bin to the front of PATH, so local binaries will always take precedence over global ones. Almost all of the time, this is what you want, but it's worth knowing that that's how it works (I recently had a bug related to this).
EDIT:
Not sure at what point in npm history this changed, but npm run <script-name> now works (don't need to do npm run-script <script-name> anymore). Possibly run-script still works as well. I'd expect it to, but I haven't tried it.
How can I set package.json up to work on both Windows and Unix?
If you
use Windows
dislike -g global install
...this is a working solution
"scripts": {
"test": "node node_modules/mocha/bin/mocha.js"
},
Notes:
putting node in front shouldn't harm, and can help on Windows (.js extension is not necessarily registered to the nodejus executable, unless you set it so. Could open a text editor, an IDE or (worse) windows scripting host, Internet Explorer…)
Adressing the script directly saves you from needing a global install. (Not judging if this is a good practice)
forward slashes help running under linux (obviously) and do work under windows (in this scenario. Also avoids a windows pitfall: backslashes if used, would need to be doubled – since they are interpreted as escaping the following letter if used solitary).
Don't use global solution, I suggest you follow what the Mocha guys say:
"scripts": {
"test": "node_modules/.bin/mocha -w"
},
Use npm i mocha --save-dev
This will save the module as a development dependency and npm will automatically set up the executables to be used within the scripts object. If you want to use the executables outside of the scripts defined in package.json, you can install it globally as well, although note that you may end up with different versions of the package.
If you only install it globally, other people won't be happy if they try to run your tests (with the standard npm test)
The new way with latest npm versions after 6.x, you needn't install mocha with global mode any more.
"scripts": { "test": "npx mocha" }
npx is installed automatically with new npm installation. It will search
mocha from node_modules/.bin or $PATH
reference: https://www.npmjs.com/package/npx

OS-independent grunt script command in NPM package.json

When the command grunt is run in a Windows shell in the same path as the grunt.js file, Windows opts to run grunt.js using the Windows Script Host. The recommended path is to explicitly call grunt.cmd.
That's all fine and dandy, but what can I do if I want to create an OS-independent script command in my NPM package.json? I can't do this if I want to also run in *nix:
"scripts": {
"dox": "grunt.cmd dox"
}
Any pointers? Or, is there a big piece of the puzzle that I'm missing? (I'm equally new to both NPM and Grunt).
I've found the solution in creating a grunt.bat file that just calls grunt.cmd:
#grunt.cmd %*
Therefore, on Windows, just invoking grunt triggers the batch file since it gets higher priority than Windows Scripting Host's picking up of grunt.js. On Linux, the regular grunt binary gets picked up. This works cross-platform for me now.
I've got the same problem: when there is tslint.js file in the root dir of the package and an npm script in package.json just calls tslint, jscript is fired by npm instead of node, resulting in "Microsoft JScript compilation error" popup.
A workaround is removing .JS from PATHEXT environment variable.

Resources