Why do we need to install gulp globally and locally? - javascript

2 manuals about gulp say that I need to install gulp first globally (with -g flag) and then one more time locally. Why do I need this?

When installing a tool globally it's to be used by a user as a command line utility anywhere, including outside of node projects. Global installs for a node project are bad because they make deployment more difficult.
npm 5.2+
The npx utility bundled with npm 5.2 solves this problem. With it you can invoke locally installed utilities like globally installed utilities (but you must begin the command with npx). For example, if you want to invoke a locally installed eslint, you can do:
npx eslint .
npm < 5.2
When used in a script field of your package.json, npm searches node_modules for the tool as well as globally installed modules, so the local install is sufficient.
So, if you are happy with (in your package.json):
"devDependencies": {
"gulp": "3.5.2"
}
"scripts": {
"test": "gulp test"
}
etc. and running with npm run test then you shouldn't need the global install at all.
Both methods are useful for getting people set up with your project since sudo isn't needed. It also means that gulp will be updated when the version is bumped in the package.json, so everyone will be using the same version of gulp when developing with your project.
Addendum:
It appears that gulp has some unusual behaviour when used globally. When used as a global install, gulp looks for a locally installed gulp to pass control to. Therefore a gulp global install requires a gulp local install to work. The answer above still stands though. Local installs are always preferable to global installs.

TLDR; Here's why:
The reason this works is because gulp tries to run your gulpfile.js using your locally installed version of gulp, see here. Hence the reason for a global and local install of gulp.
Essentially, when you install gulp locally the script isn't in your PATH and so you can't just type gulp and expect the shell to find the command. By installing it globally the gulp script gets into your PATH because the global node/bin/ directory is most likely on your path.
To respect your local dependencies though, gulp will use your locally installed version of itself to run the gulpfile.js.

You can link the globally installed gulp locally with
npm link gulp

The question "Why do we need to install gulp globally and locally?" can be broken down into the following two questions:
Why do I need to install gulp locally if I've already installed it globally?
Why do I need to install gulp globally if I've already installed it locally?
Several others have provided excellent answers to theses questions in isolation, but I thought it would be beneficial to consolidate the information in a unified answer.
Why do I need to install gulp locally if I've already installed it globally?
The rationale for installing gulp locally is comprised of several reasons:
Including the dependencies of your project locally ensures the version of gulp (or other dependencies) used is the originally intended version.
Node doesn't consider global modules by default when using require() (which you need to include gulp within your script). Ultimately, this is because the path to the global modules isn't added to NODE_PATH by default.
According to the Node development team, local modules load faster. I can't say why this is, but this would seem to be more relevant to node's use in production (i.e. run-time dependencies) than in development (i.e. dev dependencies). I suppose this is a legitimate reason as some may care about whatever minor speed advantage is gained loading local vs. global modules, but feel free to raise your eyebrow at this reason.
Why do I need to install gulp globally if I've already installed it locally?
The rationale for installing gulp globally is really just the convenience of having the gulp executable automatically found within your system path.
To avoid installing locally you can use npm link [package], but the link command as well as the install --global command doesn't seem to support the --save-dev option which means there doesn't appear to be an easy way to install gulp globally and then easily add whatever version that is to your local package.json file.
Ultimately, I believe it makes more sense to have the option of using global modules to avoid having to duplicate the installation of common tools across all your projects, especially in the case of development tools such as grunt, gulp, jshint, etc. Unfortunately it seems you end up fighting the tools a bit when you go against the grain.

Technically you don't need to install it globally if the node_modules folder in your local installation is in your PATH. Generally this isn't a good idea.
Alternatively if npm test references gulp then you can just type npm test and it'll run the local gulp.
I've never installed gulp globally -- I think it's bad form.

I'm not sure if our problem was directly related with installing gulp only locally. But we had to install a bunch of dependencies ourself. This lead to a "huge" package.json and we are not sure if it is really a great idea to install gulp only locally. We had to do so because of our build environment. But I wouldn't recommend installing gulp not globally if it isn't absolutely necessary. We faced similar problems as described in the following blog-post
None of these problems arise for any of our developers on their local machines because they all installed gulp globally. On the build system we had the described problems. If someone is interested I could dive deeper into this issue. But right now I just wanted to mention that it isn't an easy path to install gulp only locally.

Just because I haven't seen it here, if you are on MacOS or Linux, I suggest you add this to your PATH (in your bashrc etc):
node_modules/.bin
With this relative path entry, if you are sitting in the root folder of any node project, you can run any command line tool (eslint, gulp, etc. etc.) without worrying about "global installs" or npm run etc.
Once I did this, I've never installed a module globally.

Related

How do I run npx commands without prefixing `npx`

For example when I run gulp I don't have to do npx gulp.
I can omit the npx and just run gulp
How do I do this for my own package?
I've added mycommand to the package npm bin config, but I still always have to do npx mycommand for it to work.
It depends on your operating system. On a UNIX-based OS (ie. Linux or Mac) you can use the alias command:
$ alias gulp="npx gulp"
For the rest of your terminal session, you can then run:
$ gulp
to run npx gulp. However, whenever you restart your terminal program, you'll lose the alias.
To make the alias permanent, you need to add the alias command to the appropriate start-up file (eg. .bashrc, .profile, etc.) for your OS. Simply copy/paste the exact command you used before, at the end of that file, save, and restart your terminal. You'll have the alias permanently.
Aliases in Windows are also possible, but are a bit trickier; see Aliases in Windows command prompt.
You don't have to use npx gulp for gulp because it is installed globally
So, there's gulp.cmd, gulp.ps1 and gulp starting npx gulp somewhere in PATH, so you can run them from there
this answer is low effort, feel free to edit it
if you install gulp globally:
npm i -g gulp
you will be able to just run gulp
I would avoid answers suggesting global installs (npm install -g). Global installs guarantee that everyone working on a project has their own unique set of tools, and the reason companies end up with huge wiki pages on "how to get the project working locally".
You mention the "bin config", but perhaps you're misunderstanding that one. That's not for specifying commands that your app will use. If you were making a cli application, the bin section in package.json is where you would specify the commands exported by your project. For example, gulp exports the gulp command like:
"bin": {
"gulp": "./bin/gulp.js"
},
Instead, you would add dependencies needed by your application to devDependencies. This ensures that everyone using the project will get the same version of all of the tools, such as gulp, tsc
Using npx is a far better solution because you can add everything the project needs in devDependencies, and npx will use that version. For the common command line tools, an alias such as #machineghost suggests is a better way to go, but to expand on it a bit:
Sometimes, the name of the command is different from the name of the package. In those cases, the alias can use:
alias tsc='npx --package=typescript tsc'
Normally, when running npx, it will prompt to install if there is not a version found in the current project. This is often a good safeguard, because it reminds you to add it to the devDependencies of the project. However, if you really want it to "just work" like a global install, you can add the "yes" flag:
alias command=`npx -y gulp`
This will use the version specified in the current project if present, but install it and run it directly if not.

Installing gulp plugins locally vs globally

I am pretty new to Gulp and I've got a question: should I install gulp plugins (such as gulp-sass or gulp-imagemin) locally or globally? In examples around the web people mostly do it locally (with --save-dev option). As I understand, by doing so the modules are stored in the local node_modules folder, added in the local package.json as devDependencies and can be referenced to in the local gulpfile.js via require(). So, if I need to install the same modules for another project I work on, it may be accomplished by copying package.json to a new project's folder and typing in npm install in a command line tool (after getting to the project's folder). Fine.
But what if I, as a regular gulp user, don't have plans to upload and share my stuff on the npm space and not interested in maintaining devDependencies, can I in this case just install gulp plugins globally like npm install -g gulp-sass? Will they be found through a global path in my system? Is it an option on the whole, if I don't want to bother myself to copy package.json, run npm install every time I create a new project or have multiple copies of the same modules scattered around on my disk?
For plugins that you are using via gulp, what you have to do is install them locally to the project. Although you have to install gulp itself globally and locally, to run the file and then for the project to pick up the gulp based commands and functions.
The reason you should install the plugins via npm locally is so that it is specific to the project, for example if you then went to upload this project to your server or host on github then you would have to then go and have to globally install all of your packages again. If they are saved, they exist in your packages.json, this is so that when you go to run npm install to install all the packages for said project npm knows what to install.
If I can further clarify anything let me know.
A kind of "global install" for the typical case OP explained, could be to have a folder where you put your package.json with every dependencies you need for each of your projects, and run npm install from there.
And put here also your gulpfiles for each project (you could named them as you want), like gulpfile-project1.js, conf-project2.js... whatever.
Of course adjust your paths in those files accordingly.
And from this directory, run gulp using the -f flag:
gulp -f gulpfile-project1.js
So you end with this kind of scaffolding :
my_dev_directory
- project1
- dev
- main.less
- main.js
- www
- main.css
- main.js
- gulp
- node_modules
- package.json
- package-lock.json
- gulpfile-project1.js
In your gulpfiles, start to declare a const with the base path of your project to ease all path declarations, like:
const path_dev = '../project1/dev';
const path_www = '../project1/www';
This way you have only one node_modules directory installed on your disk and your projects directories contain only public files you want to upload, no dev files.
Of course one of the main drawback is that you share the same module version with all your projects, but it answered to OP's need and even if it's not recommended, not the "proper way to do", you are free to do as you want with your dev tools :)

How can I test local installation of an NPM package I've published?

I recently published a package to NPM. The package works well on my own computer, where I wrote the code, but upon npm install on a coworkers machine, I start receiving errors.
What is the best way to go about installing and testing my package on my own computer? I could trace through the errors on my coworkers computer, but I assume there is a way I can do this on my own machine.
You don't have to install it on your own computer first if you want to test it, you could write unit tests instead, since you have to require the package if you do (just like an npm install).
Check the package.json to see if all needed modules are listed under dependencies. (Delete the node_modules folder, run npm install and see what errors are given)
If there is a file called .npmrc, check what files/folders it lists to make sure it's not excluding important files from NPM.
Make sure your module has a module.exports object, to be able to access the objects/functions
If this all didn't help, it might be a more specific problem and a GitHub link would help us more

Why does grunt not work when installed globally?

I have installed grunt and grunt-cli globally using sudo npm install -g grunt... commands.
My working folder is `/opt/web', please don't ask why :)
Checking grunt version inside `/opt/web' works:
$ grunt --version
grunt-cli v0.1.13
However, I can't actually run a grunt task from there:
$ grunt
grunt-cli: The grunt command line interface. (v0.1.13)
Fatal error: Unable to find local grunt.
If you're seeing this message, either a Gruntfile wasn't found or grunt
hasn't been installed locally to your project.
If I install grunt locally, it then asks to install all it's dependencies locally (that are already installed globally (!)).
This behavior seems strange to me.
My question is:
Is this a bug or a feature? Is this by design that grunt wants to work with locally installed things only?
This is by design. See the grunt-cli readme.
The cli doesn't do anything except find and run a local copy of grunt.
This means that each project can use a version of grunt that the project specifies and is know/tested to work correctly. Given the number of critical things grunt can do, this compatibility promise is a big deal.
There is also a good blog post on the node site that talks a bit more about module installation locations.

Npm install global modules on different location node js

I am on a unix os, ubuntu, and I am experiencing a problem in installing global modules.
When I tried to look up where the node_modules folder is, I found out that npm installed some of my global modules in
/usr/lib/node_modules
and some of them are installed in
/usr/local/lib/node_modules
I have no problem before on using this global modules, until such time I tried installing a generator, that is when I first thought of looking into the directories because, after installing the generator, it says that I haven't installed the generator.
What is odd is that when I tried some of the modules, they work perfectly fine except for the other modules, saying it wasn't installed.
Is there a way to uninstall/remove/clean my computer from nodejs including its module and install it again so that it will just be using a single directory, so there won't be any confusion.
Why do you think npm installed this things in two diff. directories.
It looks to me like you have had 2 different versions of nodejs installed. Probably a packaged version and then a new release?
It works because your node folder is probably set to /usr/local/lib/node_modules
Node allways traverses the folder tree when looking for modules so if you do a require('imNotHere') it will look in:
/usr/local/lib/node_modules/imNotHere
/usr/local/node_modules/imNotHere
/usr/node_modules/imNotHere
/node_modules/imNotHere
before failing.
In your setup modules in /usr/lib/node_modules will still be caught by this

Categories