Skip to content

Commit

Permalink
Added the search and info, npm install, supervisor, and conclusion se…
Browse files Browse the repository at this point in the history
…ctions.
  • Loading branch information
croach committed Jul 9, 2012
1 parent 76eeb13 commit 0ed8c6b
Showing 1 changed file with 80 additions and 5 deletions.
85 changes: 80 additions & 5 deletions 02.md
Expand Up @@ -125,11 +125,88 @@ Now if you save that and open a new shell, hopefully everything executes properl

### Search and info

So, you've read over the docs a bit, set up tab completion, and you're ready to start installing some packages, but how do find them? Well npm offers a mechanism for doing that as well. Let's say, for example, that you're writing a command line script in node and you want to add a simple UI that uses the ncurses library. Let's do a search for that now and see if there's any library that adds that functionality to node. Go ahead and type `npm search ncurses` at the command line and you should get a list with at least one result in it for the ncurses library. Now before we decide whether or not to use that library (although in this case we don't have a lot of alternatives) let's dig a little deeper into the library using the view (or info) command. let's start by looking at what dependencies it has. Type `npm view ncurses dependencies` into the command line and you should see an empty object returned. So, the library has no dependency on any other node libraries. We can see the current version by typing `npm view ncurses version`. Maybe we also want to see what the library is licensed under to make sure that we can use it our project. To do so type `npm view ncurses licenses`. We can see that it's licensed under the MIT license which is pretty liberal and should be good for just about any project. Finally, try typing `npm view ncurses`. This returns a JSON object with all of the info on the ncurses library. All of this info is available individually by calling `npm view library attribute` where the attribute can be a several levels deep and accessible via a dotted attribute string. For example, let's grab the URL for the repository which we can see is under a separate repository object. Just type `npm view ncurses repository.url` and remember to use the tab completion on everything except the library name as that can be too slow.
Ok, so we've read over the docs a bit, set up tab completion, and we're ready to start installing some packages, right? Great, but, what do we install? How do you even know what packages are available to you? Let's say, for example, that you're writing a command line script in node and you want to add a simple UI that uses the ncurses library. How would you go about finding out if such a library is even available for node? Well one answer is to use the builtin search functionality that comes with npm. Let's go ahead and give that a try now.

### Installing packages (local vs global)
Let's continue with our scenario of finding an ncurses library and type `npm search ncurses` into the command line.

Alright we've covered quite a bit of ground with npm, but so far we haven't installed a single library. Well get ready to that now, but first, we need to discuss installing locally vs globally.
Now this could take a little while the very first time you do a search, because npm is creating an index of the available packages, but after that first time, it should go much faster.

It looks like there is an ncurses package available for node, but before we download and install it, let's just dig a bit deeper and make sure it's what we want (though in this particular situation it looks like beggars can't be choosers, since there's only one package available). For sake of argument though, let's say that we're planning on selling this application and we want to make sure that the license is compatible for commercial use. That's where npm's view (or info) command comes in handy.

The view command allows us to investigate a package's registry info. Go ahead and take a look at the docs for it by typing `npm help view`.

There's not much to this command, just give it a package name---and an optional version---and then specify the field that you want to view. Notice that the field can have subfields. I'll show you how that works in just a second, but, for now, let's exit back out of the help and try viewing the license information for the package. Type `npm view ncurses licenses` and return.

Looks like the ncurses package is developed under the MIT license, that's pretty liberal so selling our app shouldn't be an issue.

What about dependencies though? I don't really want to install anything with a ton of dependencies, so let's check the depencies for the package. Type `npm view ncurses dependencies`

And, hey look at that, no dependencies. Nice!

Finally, try typing `npm view ncurses` and hit return.

Notice that this time we didn't give the view command a field name and the result was a JSON object with all of the info on the ncurses library. The view command essentially returns either the full JSON object or the specified field that we want. The optional subfield now makes more sense doesn't it?

Let's say that I just can't stand using SVN, so I want to make sure that its repository is in something modern like Git or Mercurial. To do so, type `npm view ncurses `---by the way, while I'm thinking about it, you can use tab completion here as well, I just wouldn't advise using it on the package name, since that can take a little while---and now let's finish this using tab completion, type `repo-TAB`.`t-TAB` and hit return.

Looks like this one uses git, so I think we're good to go.

Well, I think that wraps up search and info, and I really can't think of any other goodies that I want to cover, so let's go ahead and start installing some packages with npm.

### Installing packages

Alright we've covered quite a bit of ground with npm, but so far we haven't installed a single library. Well get ready to do that now, but first, we need to discuss installing locally vs globally.

#### Local vs Global Installs

Whenever you install a package using npm you have a choice as to how you want to install it. The default way is to install the package locally, but just what does that mean? Well, to understand this, you'll first need to understand how node's `require` function works.

Whenever `require` is called from within a node file, if argument passed in isn't a native module or a filepath, node will attempt to look up the module starting at the current directory, or the directory in which the file resides, and checking for the module in a directory called `node_modules`. If it's not found there, it goes on to the parent directory and does the same thing and so on until the root directory is reached. So, for example, since I'm in my home directory, if I had a file that called `require` and I passed in the name `foo`, node would look for `/Users/croach/node_modules/foo.js`. Since it doesn't exist, it would then look for `/Users/node_modules/foo.js` and finally `/node_modules/foo.js`.

What all this means is that whenever npm installs a package locally, it will first check for a node_modules directory in the current directory and install there if it exists, and create it if id doesn't. Let's see how this works, but first let me just create a sandbox directory for me to play around in. Now, try calling `npm install express`. If you're curious, Express is a web development framework for node based on ideas from Ruby's Sinatra that we'll use later in this tutorial.

There, the package was installed, now let's do an `ls` to see that the node_modules directory was created and do an `ls node_modules` to see that the express framework has been installed within it. You can also do an `npm ls` to list all of the packages installed locally.

Notice that express is listed at the top of what looks like some type of tree. This is the dependency tree for express, so it's safe to assume that all of these packages were installed along with express. But, when we did an `ls` on the node_modules directory we didn't see any of these other packages, so where were they installed?

Well, that's part of the beauty of the way that node's `require` function works. Remember I said that it looks first inside of a node_modules folder in the same directory as the file that is requiring the module. Well that would mean that the modules required by express would be found within a node_modules folder inside of the express folder, right?

Try doing an `ls` on the express folder. Aha, so there's another node_modules in there. Now do an `ls` on that folder. Now we're seeing the four direct dependencies of express. The beauty of this mechanism is that it allows each program to install whatever dependencies it needs locally preventing any sort of version clashing that typically comes with shared dependencies.

So local installs look like the way to go for your package installation needs, so what are global installs for? Well, some packages have executables that come along with them, essentially commands that you can run that perform tasks for you. For those, you might want to install them globally. Express is one such package that comes with a command line program that you can use to create application skeletons much like the rails program for Ruby on Rails does. To install the Express package globally, you simply need to add the `-g` option to the install command. Try it out now, by typing `npm install express -g`.

Now we can call `express -h` to see the help output for the `express` program. If you'd like to see what all you have installed globally, just type `npm ls -g`. Pretty much anything that you can do with npm you can do globally by adding the `-g` option. Now let's go ahead and remove the express package globally by calling `npm uninstall express -g`. If we call `express -h` again, this time we should get back a "command not found" error.

#### Virtual Environments

So, installing packages with executables globally works, but what if we want don't want to muddy our global space with a bunch of packages that we only need for specific projects. I do a lot of programming in python and I love the virtualenv library for creating virtual environments, essentially like little gated communities, where I can install whatever I want and never have to worry about polluting the main environment.

Well, with just a little code added to our .bashrc file we can create something pretty similar. First, take another look in the local node_modules directory, this time with the `-a` option. Notice a hidden file in there that we didn't see before called `.bin`. If you take a look inside of there, you'll see a symbolic link that points right to the express command in the locally installed package. This `.bin` folder is where npm links all of the executables that each package provides. So, if we can just get that folder added to our PATH environment variable whenever we `cd` into a node application's directory, we would gain access to each package's command line programs without the need to install them globally. I've created a few bash functions to do just that. I'm not going to go over what they do here---if you're trully intersted, just ask in the comments and I'll post some notes on what the code does---but, for now, let's just head on over to the github repository that I've setup for the scripts for these screencasts. If we go to 02.md (and, yes, of course, I number them starting from 00) we can scroll down to very near the bottom of this script and copy the code. Then jump back to the terminal and open up your .bashrc file and paste the code right below the tab completion code for npm. Then, exit back out and source the .bashrc file and that should do it.

Now if you cd out of the current directory and then back into it, the virtual environment should have been created. You can check by calling `echo $PATH` and making sure that the current directory has been added to the PATH variable, but you can also just call `express -h` again to make sure that we can call it. To further make sure, call `which express` to see that it is, in fact, calling the one stored in the local `node_modules/.bin`. The nice thing about the virtual environment code is that when you leave the node application's directory, it will reset your environment. So, if we cd back out of this directory and try to call `express -h` again, you'll notice we get the "command not found" error once again.

#### Installing Supervisor

Now let's cd back into our app directory because we are going to finally install a package that we are going to put to use in the rest of this series. This package is written by the same guy that wrote npm and it's one package that I think every reall node developer needs to have.

The package that we're going to install is called supervisor and what it does is run a node service and restart it whenever a change has been made to it. So, we no longer have to shutdown our server and restart by hand everytime we make a change to our file, instead supervisor will now do that for us.

Before we install the package though, let's clean up a bit, by getting rid of Express since we're not quite ready to use that library yet. Just type `npm uninstall express`. Next, let's do a search for supervisor since I don't quite remember if the package is called node-supervisor or supervisor. Type `npm search supervisor`. With this search, we get several packages back, but the first one in the list called simply supervisor looks like the one we want.

So, if you added the virtual environment code from our last section to your .bashrc file, you can install the package locally by `npm install supervisor`. This package does provide a single executable, so you'll either want to use the virtual environment code or you'll want to install it globally.

Now that we've got it installed, let's give it a try. In your apps directory, call `supervisor app.js`. That will start our app's server up. Then let's go to our browser and hit the new post form at http://localhost:8000/posts/new/. Now let's make a quick change to our app.js file to see how supervisor works. What I'm going to do is change the URL for our new post page from /posts/new to /posts/brandnew. Save that change and notice that supervisor has spit out something. It's telling us that the server has crashed and then restarted and is running once again on port 8000. If we now refresh our page in the browser, we see that the URL has indeed changed. Let's try out the new URL, and that looks good. Now let's go back over to our code and change the URL back and save. Supervisor once again stopped and restarted the server. Now we can change the URL in the browser back to new, and voila, there is our new posts page.

## Conclusion

Alright, well that pretty much wraps up everything. I know this has been a long episode, but there was just so much to cover. You've learned about what I consider to be the most important tools in the node developer's arsenal. NVM is a great way to manage multiple node versions on one machine, and if you don't know and understand npm, you're essentially going to be useless as a node developer. Finally, we installed and took a look at supervisor, a really handy little program that helps shrink our development time by making it possible to see our changes take effect immediately in the browser.

I hope that you've all gotten something out of this episode and I look forward to talking to you all again very soon.




## Virtual Environment Code (.bashrc)

# Checks that the child directory is a subdirectory of the parent
is_subdirectory() {
Expand Down Expand Up @@ -195,8 +272,6 @@ Alright we've covered quite a bit of ground with npm, but so far we haven't inst
alias cd="env_cd"


## Supervisor

[nvm]:https://github.com/creationix/nvm
[npm]:http://npmjs.org/
[npm-g-vs-l]:http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/
Expand Down

0 comments on commit 0ed8c6b

Please sign in to comment.