Package Managers: An Introductory Guide For The Uninitiated Front-End Developer

Guide Outline

Purpose & Intended Reader

The purpose of this guide is to get the uninitiated front-end developer up and running with front-end relevant package managers. This will be accomplished by giving a foundational explanation of Node’s npm package manager with the intention of this foundation leading to a proper understanding of the Bower browser package manager.

A Note to Command Line Newcomers

Be aware, some experience with the command line is advised before reading this guide. Package managers commonly run from the command line. You can think of them as applications without a graphical user interface. The term used to describe this type of application would be command line interface or CLI. If you have a rough understanding of the command line, then great, read on. If not, I would recommend first educating yourself about your operating systems terminal because while my usage of the command line in this guide willl be simplistic, a complete command line newbie might find some of the instructions to be cryptic. Of course, don’t let a lack of knowledge around the command line stop you from reading this guide. It might be the perfect place to start learning. If you proceed with little knowledge of the command line, take comfort in the fact that I have attempted to be verbose when it comes to command line instructions.

If you need a bit of a refresher or want to prepare yourself for use of the command line interface in this guide, I would suggest watching a screencast. It is easier to understand the command line when you can see it in action. My recommendation would be the screencast, "Meet the Command Line" from Peep Code. If you’d prefer a brief and free introduction to the command line, so you can quickly get back to reading this guide, check out "A Designer’s Introduction to the Command Line".

A Note To Windows Users

Node.js, npm, and Bower are available on Windows, but I am not a Windows user. This guide is written from the perspective of a Macintosh OS X user and a *nix system is assumed. It is also known that a lot of Windows users are experiencing problems using Bower because msysgit must be installed correctly. For more information about this have a look at the Bower documentation on Github. I believe that Window users, in the web space, are used to translating what they see done in *nix systems to the Windows system, so don’t let this scare you off; just be aware that I don’t speak Windows in this guide. I speak *nix system and specifically OS X.

What is a Package Manager?

Today, it is not that uncommon for a front-end engineer to make use of a package manager. Code editors like the Sublime text editor provides a package manager called Sublime Package Control. Many of the advances in front-end tooling are being developed on the Node.js platform (i.e. grunt.js) and installation of these tools are handled by the npm package manager. In recent months, efforts have been made to bring the concept of a package manager to the browser. The front runners in this effort are Jam, Ender, volo, Component, browserify, and the one we will discuss in this guide, Bower. Each of these have a different twist on the role of a brower package manager.

If you are not aware, a package manager manages assets (i.e. installs, upgrades, removes, manages dependencies) used in a program. For example, npm manages JavaScript modules called packages and Bower manages front-end components (i.e. css, html, and JavaScript) called components. Both npm and Bower make use of a registry which keeps track of a package/component details like name, description, version, author, dependencies, and location. In some cases, the registry will even store the packages themselves, which is the case with npm packages.

In this guide, we are going to briefly take a look at the Node.js package manager in order to introduce the concept of a package manager. Then we will take this knowledge and apply it to an examination of Bower. The reason that we are starting with npm is because npm is used to install Bower. That is, Bower itself is a package in the npm registry.

Understanding npm first will complement the learning process when it comes time to grokking a browser package manager like Bower. The information discussed in this guide will pertain mostly to the consumption of npm packages. I am leaving out details around authoring npm packages and customizing npm because this is typically not a front-end focused endeavor.

What is npm?

Npm is the package manager that comes preinstalled with the Node.js server platform. It is used to install node programs from the npm registry. In short, it is a tool that aids a developer as they install and manager third party node programs. Don’t confuse npm with the commonJS require() statement. It is not used to load code, it is used to install code and manage code dependencies from the command line.

The packages found in the npm registry can range from simple helper libraries like underscore.js to task runners like grunt.js that are not intended for use on a single application alone.

Specifically, an npm package, as defined by the npm documentation is:

If you are not familiar with Node.js, allow me to quickly catch you up to speed. You can think of node as a server-side platform written in JavaScript. Node.js replaces something like Apache and PHP with an evented I/O JavaScript environment built on Chrome’s JavaScript V8 runtime. Basicly, node means programming on the server, in JavaScript using an event loop instead of the more common multithreaded environments like Apache. For the purpose of this guide, Node.js is necessary to get npm up and running, but we're not going to spend much time learning node itself. I’m going to cover installing Node.js locally and then quickly move to discussing npm. If you would like a more detailed introduction than what I have provided here I suggest giving, "The Art of Node" a read.

Installing npm (and Node.js)

Installing npm is simple, given that it is automatically installed when you install Node.js. Don’t worry, Node.js is not that difficult to install either. In a web browser, visit nodejs.org and click on the install button (Note: installers are only avaliable for Windows & OS X). This will download an installer program to your local computer. From here, I will assume you know how to install a program on your computer.

As a front-end engineer I’ve had little reason to leverage anything but the auto installers provided by the node project. The installer makes installation and upgrading a breeze. However, you should be aware that it is possible to download, build, and install Node.js manually. For the purpose of getting up and running fast with Node, I suggest you simply use the installers.

If you have not run the install program yet, do so now. If you already have Node.js installed make sure it’s updated to the latest version. Updating Node can be accomplished by running the latest installer.

Once the installation of Node.js is complete, open a command line (i.e. open what is called the terminal in osx) and run:

$ node --version

You should see the version of Node.js just installed, returned to the command line:

$ v0.10.0

If Node.js was installed from the installer this also means that npm is installed, buts let’s verify. From the command line prompt type and hit enter:

$ npm -version

You should see the version of npm returned, something like:

$ 1.2.14

You should now have node.js and npm installed on your local system.

Configuring npm

In this guide, we are not going to configure npm we are simply going to use it in the state it is installed by Node.js. In this state we are relying on the defaults provided by npm. However, let’s quickly review how to view npm configurations.

To view the current global settings for npm from the command line run:

$ npm config list -l

This will output to the terminal all of the global settings and their values. I’m not going to output all of the values here in this guide because its a long list, but you should do a quick scan of the settings just to be aware of some of the configuration options.

Npm has a great deal of configuration settings and sources (6 to be exact), for additional information about the settings have a look at the config doucumentation at https://npmjs.org/doc/config.html.

Updating npm

The advantage of using the installers provided by the Node.js project is that in order to upgrade npm and node, one can simply download a new installer and install Node.js again. After the installer is used, node and possibly npm are updated. I personally use the node installer for keeping npm updated. If, however you do not want to keep your version of npm in sync with the version contained in the installer you can always update npm with the following npm command.

$ npm update -global npm

If that command looks confusing, remember that npm is a node package itself so npm can update itself, using its own api. If what I just said is perplexing, just keep reading I’m hoping by the time we are done talking about npm it’ll make more sense.

Uninstalling npm

To uninstall npm, the following npm command can be used, but we are not going to actually uninstall npm. I'm not even sure I am aware of a use case for uninstalling npm, but this information is provided so that you are aware of how to uninstall it.

$ sudo npm uninstall -global npm 

Don't be mystified by the fact the npm can uninstall itself, remember npm is a package, so we can use npm to install as well as remove npm.

Notes:

Where can I find npm documentation?

Online you can find a project readme at https://npmjs.org/doc/README.html and the command line documentation (i.e. the commands you call to make npm do something) at https://npmjs.org/doc/.

It is also possible to view the information you find on the npmjs.org site from the command line.

Using the help command, we can view a summary of npm commands. To view this information run the npm help command on your system’s command line.

$ npm help

This will output the following:

Usage: npm <command>

where <command> is one of:
    add-user, adduser, apihelp, author, bin, bugs, c, cache,
    completion, config, ddp, dedupe, deprecate, docs, edit,
    explore, faq, find, find-dupes, get, help, help-search,
    home, i, info, init, install, isntall, issues, la, link,
    list, ll, ln, login, ls, outdated, owner, pack, prefix,
    prune, publish, r, rb, rebuild, remove, restart, rm, root,
    run-script, s, se, search, set, show, shrinkwrap, star,
    stars, start, stop, submodule, tag, test, tst, un,
    uninstall, unlink, unpublish, unstar, up, update, version,
    view, whoami

npm <cmd> -h     quick help on <cmd>
npm -l           display full usage info
npm faq          commonly asked questions
npm help <term>  search for help on <term>
npm help npm     involved overview

The above, of course, is just an overview. If you would like a full display of commands, you can run:

$ npm -l

Another useful read pertaining to npm is the FAQ document. This document can be viewed in the command line by running the npm faq command or online at https://npmjs.org/doc/faq.html.

Notes:

What is the npm registry?

Node.js packages which are intended for public use can be published to the npm registry. The point of publishing a package to the registry is so that the package can be used and installed by anyone. Think of the npm registry as a repository of public node programs available for installation into your program by name. For example, when you install node, node by default includes the npm package from the npm registry. Addtional information about the registry can be found at: https://npmjs.org/doc/registry.html.

Searching the npm registry

Online you can search for npm packeges at https://npmjs.org/ or from the command line you can search the registry by using the following command.

$ npm search [search terms ...]

I am not recommending it, but running the npm search command with no keyword term added will return a list of all the packages in the registry. It is, of course, best to either provide a search term or a regular expression (If a term starts with /, then it's interpreted as a regular expression) as a value for the search command because the registry is rather large and the kitchen sink list returned is not very helpful.

Regardless of how you search the registry, what you need to find is the name of the package you want to install. This is the point of searching, to find a name and use that name to install a package.

Installing and Updating packages from the npm registry

Installing Packages locally

To install the latest version of a package locally, all that is required is to run npm install [package name] from the command line in the directory you want the package installed. This is considered installing a package locally. When you install a package a couple of things occur. Below I loosely examine these occurrences in order.

  1. NPM examines the current directory you are calling the npm command from and begins walking up the directory tree structure checking for a folder that contains either a package.json file or a node_modules folder. When one of these is found, npm will consider that directory, the current directory, for the purpose of running npm commands. If neither are found, then the current directory in which the searching started will be used as the npm current directory.
  2. If a ./node_modules directory is already in the directory determined in step 1, it will place the packages inside of ./node_modules. If no ./node_modules directory is found npm will create the directory and then place packages in it.
  3. Once packages have been installed npm will attempt to read each package's package.json file being installed, and examining it for a list of dependencies. If dependencies are found, npm will install these dependencies in a folder called node_modules contained inside of the package's directory being installed.

Let’s give installing a package a try so we can examine what occurs as the package is installed.

On your local computer, from the command line, create an empty folder/directory wherever you you would like (e.g. could be an empty directory/folder on your desktop), and cd into that directory.

With that directory open on the command line, type:

$ npm install backbone

The above npm command is telling npm to grab backbone from the registry and install backbone into the current directory. Since our directory was empty, npm creates a folder called node_modules and places backbone and its dependencies inside this folder. Let’s examine the tree structure, shown below, after the npm install command install's backbone.

+-- node_modules
    +-- backbone
        +-- CNAME
        +-- CONTRIBUTING.md
        +-- LICENSE
        +-- README.md
        +-- backbone-min.js
        +-- backbone-min.map
        +-- backbone.js
        +-- index.js
        +-- node_modules
        ¦   +-- underscore
        ¦       +-- CNAME
        ¦       +-- CONTRIBUTING.md
        ¦       +-- LICENSE
        ¦       +-- README.md
        ¦       +-- favicon.ico
        ¦       +-- index.html
        ¦       +-- index.js
        ¦       +-- package.json
        ¦       +-- underscore-min.js
        ¦       +-- underscore.js
        +-- package.json

(FYI the tree command, used to create the tree structure just shown is not available by default on osx I had to install it.)

Let’s review what just happened by having npm install backbone.

  1. npm install backbone was ran from our empty directory
  2. npm scanned the parent file tree structure looking for a package.json file or a node_modules folder. It did not find anything so it assumes you want to install backbone in the current directory you called the npm install command from.
  3. npm creates a node_modules folder, because one is not available
  4. npm installs backbone from http://registry.npmjs.org/backbone/-/backbone-1.0.0.tgz, unpacking it and placing it into the node_modules folder.
  5. npm examined the package.json file in the backone directory, found a dependency, and then created another node_modules folder in the backbone directory which is created so that underscore dependency can be placed inside it.

The empty folder we created, in which we had npm install backbone would be considered the root directory of the project we are working on. Because we now have backbone locally installed, we can use it in our node project by simply creating a JavaScript file and requiring (i.e. require(‘backone’)) into that file.

So let’s do that. In the same directory, create a file called getBackboneVersion.js and place the following code (leave out the semicolons for now) in that file and save this file:

var backbone = require('backbone')
console.log(backbone.VERSION)

The simple javascript code in getBackboneVersion.js requires (i.e. searches for a node_modules folder in our application’s directory and looks inside of it for backbone and its dependencies) the backbone library into scope so that it can be used by code written in the file. Having backbone required() into the scope of the getBackboneVersion.js file is not unlike including a javascript file using an html <script> element, into an html page. Of course, a major difference in the correlation just stated is, backbone when loaded into an html page won’t function properly unless you remember to also load underscore. This is not the case with the the node environment. Requiring a module in the node environment, means the dependencies are programmatically resolved by npm and properly scoped.

To see node run this file make sure the command line is open to the directory that contains getBackboneVersion.js and run the following command

$ node getBackboneVersion.js

In the command line, you should see the results of running the JavaScript code contained in the getBackboneVersion.js file. It will return the version of backbone (i.e. 1.0.0) installed locally by npm.

To review, we installed an npm package and then used that package in a very tiny node application allowing npm to manage the package's dependencies.

However, not all node packages are used specifically in node programs like what was just accomplished by installing backbone and using it in a node program. Many of the packages found in npm are command line programs themselves (like npm) which need to be installed globally. We will look at globally installed packages next.

Note:

Installing packages globally

It is possible to install node packages globally as opposed to locally. This is typically only done when you are not using require() to include the package in a project (i.e. like we did with backbone) and the nature of the package is that of a tool (e.g. grunt.js). In other words, globally installed packages are not typically used as hard dependencies in a node project. Npm itself is a good example of this type of node package.

When you install a package globally the package is typically that of a tool used during development by way of a command line interface provided by the package. These types of global packages typically rely on correctly establishing (e.g. binaries end up in your PATH environment variable) the executables in the package to be executed from the local shell/command line. This might be hard to understand, so let’s examine it in action by installing one such tool.

Working from the directory root where backbone was just installed, let’s also install from here the jshint package that is intended to be used globally.

From the command line run:

$ sudo npm install -global jshint

Notice the addition of the -global (which can also be written in shorthand as -g) indicating that we would like to install jshint globally. Additionally, notice that we had to use sudo to install the package globally. Using sudo permits the package to be installed globally by requiring the current user to provide a user password (i.e. what you login into the computer with) in order for the installation to be completed. Provide your password, so installation can be completed and once the package is installed lets confirm that it was not installed locally using the npm list command.

$ npm list

The list command will give us a list of all of the local modules and their dependencies. Shown below:

+-- backbone@1.0.0
  +-- underscore@1.4.4

As expected the jshint package is not found locally because we installed it globally. Let’s list out all global packages installed and verify that it has been installed globally.

$ npm -global list

Running the list command with the global flag should print out all of the global packages installed by npm to the console. This list might be long if you already have node and several other global packages installed. Just verify that the jshint package and it's directory structure were part of the results printed to the command line. It should look something like this:

/usr/local/lib
+-- jshint@1.1.0
¦ +-- cli@0.4.4-2
¦ ¦ +-- glob@3.1.21
¦ ¦   +-- graceful-fs@1.2.0
¦ ¦   +-- inherits@1.0.0
¦ +-- esprima@1.1.0-dev
¦ +-- minimatch@0.2.11
¦ ¦ +-- lru-cache@2.2.2
¦ ¦ +-- sigmund@1.0.0
¦ +-- peakle@0.0.1
¦ +-- shelljs@0.1.2
¦ +-- underscore@1.4.4

Notice that it lists all of the jshint dependencies/versions used by jshint.

We have confirmed that jshint and its dependencies have been successfully installed globally. Now let’s take it for a spin. Remember, global packages typically contain programs that are not project focused but, instead, provide some sort of command line interface for running executables found in the package. For example, we can now run jshint on our getBackboneVersion.js from the command line by running the following command:

$ jshint getBackboneVersion.js

Notice that we just referenced jshint like it was an application available from the command line. Running jshint on the getBackboneVersion.js file sends us a warning. Oh, that’s right, we left out the semicolons, and jshint is telling us as much, shown below:

text.js: line 1, col 35, Missing semicolon.
text.js: line 3, col 30, Missing semicolon.

2 errors

The takeaway here is the node packages come in two flavors, local and global. Local packages typically are used in node programs while global packages typically are programs themselves which have a command line interface or CLI.

Notes:

Updating packages

Updating a package is not complicated in the slightest. To update a package to the latest version simply use the update command. Below I show the npm commands to update the backbone and jshint packages.

$ npm update backbone
$ npm update jshint -global

These packages are, of course, up to date because we just installed them.

Note:

Listing npm packages

Remembering what packages are installed and their dependencies should not be left to memory. One can always get a tree list in the command line of the global or local modules and dependencies by using the npm list command to check both local and global node_modules directories. We have already seen these in use, but here are the commands again.

$ npm list 
$ npm list -global

Uninstalling npm packages

To remove everything that npm has installed pertaining to a specific package the npm uninstall command combined with the name of the package is used. For example, to remove both the backbone and jshint packages, you could run the following in two commands.

$ npm uninstall backbone
$ sudo npm uninstall jshint -global

If you ran these uninstall commands, make sure you re-install before proceeding with the rest of this guide.

package.json file

Package details are stored in package.json

Each npm package will contain a package.json file, typically, in the root directory. This json document contains data about the project as well as configuration values for npm and project dependencies. If you do some looking you'll find package.json file for all of the packages (backbone & jshint) we've installed. Npm uses this packages.json file as instructions for how packages and there dependencies should be installed.

Below, I provide a comprehensive example of a fictitious package.json file.

{
  "name":"name",
  "preferGlobal":false,
  "version":"0.0.0",
  "author":"john doe",
  "description":"",
  "bugs":{"url":"http://github.com/owner/project/issues","email":""},
  "contributors":[{"name":"John Bow","email":"johnbow@jb.com"}],
  "bin":{"http-server":"./bin/http-server"},
  "scripts":{"start":"node ./bin/http-server"},
  "main":"./lib/http-server",
  "repository":{"type":"git","url":"https://github.com/jd"},
  "keywords":["cli","http","server"],
  "dependencies":{"package":"0.1.x"},
  "analyze":false,
  "devDependencies":{"package":"0.5.x"},
  "bundledDependencies":["package"],
  "license":"MIT",
  "files":[],
  "man":{},
  "config":{},
  "engines":{"node":">=0.6"},
  "engineStrict":true,
  "os":"darwin",
  "cpu":"x64",
  "private":false,
  "publishConfig":{}
}

A lot of these properties are self explanatory. For detailed information pertaining to each of these properties, you can look at the npm documentation or use the interactive package.json guide to get details about the most common properties. Keep in mind that some of these properties are leveraged by node as well as npm.

Notes:

Viewing package.json before installing

You do not have to install a package locally or globally to see a packages package.json file. From the command line, use the npm command npm info [package name] to output the contents of the packages, package.json file from the registry. This will download the package.json for viewing on the command line.

For example, below I output the package.json file for the backbone node package, using the npm info backbone command.

{ name: 'backbone',
  description: 'Give your JS App some Backbone with Models, Views, Collections, and Events.',
  'dist-tags': { stable: '1.0.0', latest: '1.0.0' },
  versions: 
   [ '0.1.1',
     '0.1.2',
     '0.2.0',
     '0.3.0',
     '0.3.1',
     '0.3.2',
     '0.3.3',
     '0.5.0',
     '0.5.1',
     '0.5.2',
     '0.5.3',
     '0.9.0',
     '0.9.1',
     '0.9.2',
     '0.9.9',
     '0.9.10',
     '1.0.0' ],
  maintainers: 'jashkenas <jashkenas@gmail.com>',
  author: 'Jeremy Ashkenas <jeremy@documentcloud.org>',
  time: 
   { '0.1.1': '2011-07-01T17:58:59.581Z',
     '0.1.2': '2011-07-01T17:58:59.581Z',
     '0.2.0': '2011-07-01T17:58:59.581Z',
     '0.3.0': '2011-07-01T17:58:59.581Z',
     '0.3.1': '2011-07-01T17:58:59.581Z',
     '0.3.2': '2011-07-01T17:58:59.581Z',
     '0.3.3': '2011-07-01T17:58:59.581Z',
     '0.5.0': '2011-07-01T17:58:59.581Z',
     '0.5.1': '2011-07-05T14:00:26.305Z',
     '0.5.2': '2011-07-26T17:32:13.339Z',
     '0.5.3': '2011-08-09T14:39:31.451Z',
     '0.9.0': '2012-01-30T21:25:46.270Z',
     '0.9.1': '2012-02-02T21:55:21.701Z',
     '0.9.2': '2012-03-21T18:57:24.034Z',
     '0.9.9': '2012-12-13T22:48:34.385Z',
     '0.9.10': '2013-01-15T20:33:40.450Z',
     '1.0.0': '2013-03-20T12:16:51.375Z' },
  users: 
   { dodo: true,
     bat: true,
     sjonnet: true,
     fgribreau: true,
     sjonnet19: true,
     gillesruppert: true,
     m42am: true,
     mahnunchik: true,
     lupomontero: true,
     leesei: true },
  url: 'http://backbonejs.org',
  keywords: 
   [ 'model',
     'view',
     'controller',
     'router',
     'server',
     'client',
     'browser' ],
  dependencies: { underscore: '>=1.4.3' },
  devDependencies: 
   { phantomjs: '1.8.1-3',
     docco: '0.6.1',
     'coffee-script': '1.6.1' },
  scripts: { test: 'phantomjs test/vendor/runner.js test/index.html?noglobals=true && coffee test/model.coffee' },
  main: 'backbone.js',
  version: '1.0.0',
  readmeFilename: 'README.md',
  dist: 
   { shasum: '5e146e1efa8a5361462e578377c39ed0f16b0b4c',
     tarball: 'http://registry.npmjs.org/backbone/-/backbone-1.0.0.tgz' },
  directories: {} }

A good deal of valuable information can be obtained by using the info command. I will often use it to review a package before installing it.

Interactively create a package.json file

Npm provides an interactive process for creating a package.json file. This simply means, from the command line, you are asked some questions and the responses are placed inside of a pacakge.json file that npm creates.

To test this auto creation feature provided by npm, return to the directory where we installed the node backbone package and created the getBackboneVersion.js file. In this directory, run:

$ npm init

Next, you will be asked a series of questions. Below I show the questions and the responses you should give in the context of the small node application we created earlier.

name: (getBackboneVersion) get-backbone-version
version: (0.0.0) 0.1.0
description: get backbone version used
entry point: (getBackboneVersion.js) getBackboneVersion.js
test command: n/a
git repository: n/a
keywords: backbone, version
author: cody lindley
license: (BSD) MIT

After answering the questions, it will preview in the command line the contents of the package.json file.

{
  "name": "get-backbone-version",
  "version": "0.1.0",
  "description": "get backbone version used",
  "main": "getBackboneVersion.js",
  "dependencies": {"backbone": "~1.0.0"},
  "devDependencies": {},
  "scripts": {"test": "n/a"},
  "repository": {"type": "git","url": "n/a"},
  "keywords": ["backbone","version"],
  "author": "cody lindley",
  "license": "MIT"
}

To accept these values enter y or yes into the command line and press enter. You will now have a package.json file with the values you entered into the interactive questionnaire, created for you and placed in the project’s root directory. Notice that npm, assumed that backbone was a dependency and went ahead added this dependencies value. This is because the component was found in the node_modules directory.

With a package.json file in place for get-backbone-version node program, it is now possible for us to publish our program to the npm registry. We are not going to do that now, but it would be completely possible with the package.json file in place.

Let’s say, we did publish our simplistic get-backbone-version package to npm and installed it in another node project. What you need understand here is that our package would be placed in the node_modules folder (i.e. in a folder name get-backbone-version) and backbone and underscore.js would automatically be installed as well, because the package.json has backbone as a dependency.

The dependency installation and resolution can handle some fairly complex relationships.

If this is all sinking in, it should occur to you that npm removes the management of assets by a human. In front-end development this has historically been human powered. Npm removes the human variable when it comes to managing assets and tools on the server-side.

Wouldn’t it be great if there was a tool that could do this for us when working on browser projects (i.e. html, css, and js projects)?

Notes:

Telling npm to Install dependencies from package.json

Let’s pretend that instead of publishing our “get-backbone-version” to npm, we had placed it on Github in a public repository. Typically in this scenario, we would exclude (i.e. leveraging a gitignore) the node_modules directory. The reason being that installing dependencies can be resolved by npm so it’s unnecessary to include packages in the source code.

If you are not already there, navigate to the get-backbone-version node project root directory in the command and delete the node_modules directory (e.g. rm -rf node_modules or simply delete the directory using an os file GUI).

Let’s just pretend that the current state of the local directory, with the node_modules directory removed, is in the same state it would be had we cloned this fictitious Github repository.

If we attempt to run the getBackboneVersion.js we’d, of course, get an error because backbone and its dependencies are missing. Remember, we deleted the node_moduels directory and have no backbone to require(). To fix that, we need to install the packages getBackboneVersion.js loads. Or said another way, we need to install the dependencies. From the command line run the install command with no argument flags.

$ npm install

Running install with no argument flags will tell npm to create a node_modules folder and if one is missing, then load all the dependencies identified in by the package.json file. With the dependencies installed, the get-backbone-version package will now run without errors.

When you install a package from the registry, installation of dependencies is automatic. The install command allows us to manually tell npm to find a package.json file and do it's thing.

Wait, I'm a front-end engineer and NPM is for backend JS developers!

You might be thinking, npm is great, but I am a front-end engineer. Why should I spend my time learning it or a backend-end environment like node?

Node.js and npm, regardless of if you write node code, can open the door to a new set of tools specifically targeted for use by front-end minded developers. For example, things such as grunt.js and jshint have become common tools used by modern front-end engineers. All of which run on Node.js and require a developer to have an understanding of npm. Additionally, by taking the time to roughly understand the purpose of npm and making it a tool in the toolbox, a front-end engineer will naturally begin to see the value provided by a browser package manager.

What is Bower?

In short, and stated already in the introduction, Bower is a package manager for the web or, more specifically, browser development. Just think npm, but for browser development instead of node development. Bower’s purpose is to manage front-end assets, which can include not just javascript files, but also html, css, image, and font files. Because of this, Bower, unlike npm, can have multiple files (e.g. .js, .css, .html, .png, .ttf) which are considered the main file(s). Bower semantically considers these main files, when packaged together, a component.

Notes:

What Bower is not

Just like npm, Bower’s focus is on installing assets. Unlike npm, it is agnostic as it pertains to how the assets are included/required modularly in code. Npm dictates that packages follow the commonJS specification while Bower does not make any assumptions about how the assets being packaged are written or included. This also separates Bower from other current offerings that enforce a modular specification like AMD (e.g. Jam) or commonJS (e.g. browserify).

Bower is not opinionated about the structure of the code in the files or how it is loaded. This means that Bower is not built with opinions on scripting loader or modular loading. It is not at all concerned with how the asset's it manages get included in your web pages. Its philosophy, and therefore function, is to be a generic tool that installs assets from the command line and resolve dependencies, all while being “loader-agnostic”. Because of this philosophy, Bower is rather simplistic compared to something like npm or other package managers competing with Bower.

Another detail that separates npm from Bower is the fact that Bower does not store packages in the registry. Bower’s registry simply stores the name of a package and its endpoint. We’ll get into more detail in a minute, just realize that the bower registry manages references to files, and does not store a tar archive itself. It has been said that you can think of the Bower registry as a URL shortening service, because it essentially provides a named shortcut to the location (i.e endpoint) of a packaged component.

Installing, Configuring, and removing Bower

Installing Bower

Bower is a node package that can be installed using npm, just like backbone or jshint. Like the Bower documentation states, “how meta”, meaning a package manager (i.e. npm) is used to install and run another package manager. What I just explained, hopefully, is not overly cryptic considering the coverage of npm done in the first part of this guide. If what I just said is still a pretty mussy concept I’d suggest re-reading the beginning section of this guide where npm is presented.

Before installing Bower you should verify that Node.js and npm are available, which they should be because we installed them in the first part of this guide. From the command line run the following commands verifying that node and npm are installed.

$ node --version; npm -version

If you see two versions numbers in the terminal after running the previous commands, then everything is good.

Next, I recommend having Git installed given that Bower is built on top of Git. It is not an absolute requirement to have it, but using Bower without Git is certainly not the common use case. To verify you have Git you can run the following command:

$ git --version

You should see a Git version printed to the command line. If you don't see a version number your system does not have Git installed. To install Git download an installer, and run it. Make sure you have Git installed before proceeding.

Once you have node, npm and Git properly installed Bower can be installed by running the familiar npm install command:

$ sudo npm install bower -global

Bower assumes system wide use and therefore it should be installed globally. You can think of Bower much like the jshint package we installed, in that, it's use can be viewed as a local development aid for any project developed on your local system.

Configuring Bower, using with the .bowerrc file

Configuration for Bower does not happen from the command line. Bower’s per project configuration happens by including a .bowerrc json file in the root of a project folder. Or, optionally, you can create a global configuration .bowerrc file in your home folder (this can be found on osx at ~/bowerrc). Project based .bowerrc files will inherit from the global file but have the final say when running Bower from a project root directory.

By default, and without setting up a .bowerrc file, Bower will use the following default configuration values.

{
  "directory" : "components",
  "json"      : "bower.json",
  "endpoint"  : "https://Bower.herokuapp.com",
  "searchpath"  : "",
  "shorthand_resolver" : ""
}

Using a .bowerrc with custom values allows us to set the following configuration properties.

At this time we’re not going create a .bowerrc file, we’ll simply rely on the defaults. Specifically, this means that Bower components will be found and searched for at the public Bower registry and installed locally in a directory name “components”. Bower will also assumes that by default a components manifest is called, “bower.json”.

Removing Bower

Use the familiar npm uninstall command to remove Bower.

$ sudo npm uninstall -global bower

Don’t forget that Bower is installed globally and the global flag should be used to remove it as well.

Removing Bower will not remove components previously installed by Bower. Removing Bower, follows the same rules that removing any npm package would follow.

Bower Documentation & Help

As of today, Bower does not replicate its command line documentation online like npm. Bower does have a general readme page online to help get you started but it is certainly no replacement for the documentation available from the command line. Just like npm, getting a quick overview of the Bower commands can be accomplished by running:

$ bower help

This will print the following api overview to the terminal. It is a small, simple api, so make sure you give it a close read.

Usage:

    bower <command> <options>

Options:

    --no-color - Do not print colors (available in all commands)

Commands:

    help, install, list, ls, uninstall, update, link, lookup, info, init, register, search, cache-clean, completion

To get details about each Bower command, add the command name to the end of the help command. For example, running Bower help list will output to the command line (shown below) details about the list command:

Usage:

    Bower list
    Bower ls

Options:

    --map      - Generates a deep dependency JSON source mapping
    --paths    - Generates a simple JSON source mapping
    --sources  - Generates list of source files in order of dependency
    --offline  - Avoid checking for newer versions
    --no-color - Do not print colors

Description:

    Lists all packages

We’re not going to review all the documentation for all the Bower commands now, but it’s certainly a worthwhile endeavor given that its such a small command line api.

Bower Endpoints

Before installing any Bower components, it is important to understand Bower endpoints. Think of an endpoint as the actual location for a component you are installing. By default, Bower will search for a components endpoint in the Bower registry. The registry is located at https://bower.herokuapp.com/packages and I’ve setup a json preview of the registry here, http://jsonmate.com/permalink/71a30dd682d0aac7eb0367b49c04eecc. What you are viewing by visiting the previous link is a json snap shot that contains all of the packages registered with Bower on the day I copied the json feed. Basically, this is a json object that contains a reference, by name, to Git endpoints.

Installing components from a Git endpoint stored in the registry is only one type of Bower endpoint. Below I detail additional Bower endpoint options that can be indicated when using the install command, including the default method just mentioned.

Registry Endpoint (i.e. a named Git endpoint) - a Bower register name and git repository from the registry:

bower install backbone

Any Git Endpoint - does not have to be Github could be any public or private Git repository:

bower install git://github.com/documentcloud/backbone.git

URL endpoint - a url reference to a file (e.g. .js .css, .html etc..). A zip or tar.gz file will be extracted:

bower install http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js

Local Enpoint - a local path to a file or Git repo:

bower install ./some/path/relative/to/this/directory/backbone.js

Searching for Bower Components/Endpoints

Searching the registry

To install a Bower component by name, a search of the registry for the name of the component can be done from the command line or online through a browser UI. To search the registry using the command line use the Bower search command. For example, invoking the command below searches the registry for any components that contain the string "backbone" in the name of the component.

$ bower search backbone

The previous search command, for backbone, if actually run from the command line will return a long list of components that all contained the word "backbone". Currently, the search command only does keyword searches and searches only the names of components.

If you prefer searching using a GUI and not the command line, Sindre Sorhus created a public UI for search the registry.

Searching outside of the registry

Bower’s ability to install a component from public url’s (git repos, files, or zipped files) naturally means any mechanism for searching the web can also provide endpoints to components that Bower can install. Consider that any of the url’s found on http://cdnjs.com/ can be installed by Bower. When this is done, unless the url endpoint is a group of compressed files, Bower will only install a single file with associating bower.json manifest. This reality solidifies that not all components have an associated bower.json manifest file, unless the component comes from the registry. And, even then, this does not stop an author of a component from removing the bower.json file after its been registered.

Searching your own private registry

We are not going to go into detail about setting up your own registry, but you should be aware it is completely possible to configure Bower to search (set this up in the .bowerrc file) a private registry alone or in private registry in addition to the public repository. This can be set up and configured using a .bowerrc file (e.g. setting the searchpath property). The advantage in creating your own registry is that it can sit behind a firewall on a private network. The Bower project has even provided a bower-server to aid you in this setup.

A Bower Components Lifecycle: Installing, Updating, Listing and Removing

Installing, updating, listing and removing Bower components is done with an api that is similar to npm’s. The major difference here is found in the varying ways in which a component can be installed based on the differing endpoint options.

To get an idea of Bowers api, let’s walk through the lifecycle of a Bower component. Specifically, we will be installing, updating, listing, and removing a registry component called "jquery-ui".

Create a new project directory on your local system and then open a command line so that you are running commands from the directory you created.

Before we install the "jquery-ui" component lets get some information about the component. To do that, let’s use the Bower info command shown below.

$ bower info jquery-ui

Printed to the command line you should see a list of "jquery-ui" version’s available, something similar to the following:

  Versions:
    - 1.10.2
    - 1.10.1
    - 1.10.0
    - 1.9.2
    - 1.9.1
    - 1.9.0
    - 1.8.23

It's not much information but its certainly better than nothing. We are going to use this information to install an older version of the "jquery-ui" component.

Let’s now install the 1.10.1 version of the "jquery-ui" component using the install command and making sure we specify the 1.10.1 version we want installed by adding this information to the end of the component name (e.g. jquery-ui#1.10.1).

$ bower install jquery-ui#1.10.1

Running this command results, roughly, in Bower doing the following ordered tasks:

  1. Fetch the "jquery-ui" component endpoint from the registry. Download the repository from github that is tagged as version 1.10.1 and cache it locally so future installations of this component can be pulled from cache in the future.
  2. Reference .bowerrc file for the directory location to which the component should be installed and install the component to that directory. By default, Bower will check to see if the directory the command was invoked from contains a components directory. If it does, it will add the component to that directory. If not, the components directory is created and the component is placed in this new directory.
  3. Check the root directory of the "jquery-ui" component being installed for a bower.json file. If available, check the file for any indicated dependencies. If a dependency is indicated in the bower.json file then fetch that component and place it in the component directory alongside the "jquery-ui" component (make note that the dependency was not placed inside of the "jquery-ui" directory but alongside it. This is considered a flat dependency tree and not similar to how npm handles its dependencies).

We can verify that installing the "jquery-ui" component resulted in the above actions by viewing the directories created after the installation. It should resemble the following new structure.

+-- components
    +-- jquery
    +-- jquery-ui

Notice that the "jquery-ui" component did in fact have a dependency and Bower went ahead and installed that dependency in the components directory. Just to hit this fact home let’s open the bower.json file for the "jquery-ui" component and verify the dependency the value.

{
  "name": "jquery-ui",
  "version": "1.10.2",
  "main": "./ui/jquery-ui.custom.js",
  "dependencies": {
    "jquery": ">= 1.8"
  }
}

This file indicates, as did the fact the Bower installed "jquery" along with the "jquery-ui" plugin, that a version of jquery greater that 1.8 is a dependency.

Using the list command we can also get a tree like view of all the components installed locally detailing not only what is currently installed, but also any dependencies of the components installed.

Run Bower list from the command line will output:

+-- jquery#1.9.1
+-- jquery-ui#1.10.1 (1.10.2 now available)
  +-- jquery#1.9.1

This confirms that we have two components installed. "jquery" and "jquery-ui", and that "jquery-ui" has a dependency on jquery. Notice also, that the list command informs us when a package is outdated. Lets now update the "jquery-ui" component.

Use the Bower update command along with the package name to update the "jquery-ui" component to the latest version.

$ bower update jquery-ui

This will update the jquery-ui package from 1.10.1 to 1.10.2.

Notes:

To uninstall the "jquery-ui" component simply run the uninstall command and tell it which component you’d like to remove.

$ bower uninstall jquery-ui

Go ahead and run the uninstall command now if you haven't. Now run the list command, after removing the "jquery-ui" component, you’ll notice that not only did it remove the "jquery-ui" component it also removed its "jquery" dependency. Had we had another component that was dependant on jquery it would have remained. So, Bower not only intelligently installs dependencies, it also attempts to intelligently clean up after itself.

Using Bower Components

Bower is not opinionated when it comes to how a component gets used, or the format (e.g., AMD, CommonJS, etc.) in which a component needs to be written in order to be managed. You decide how a component gets into your web pages, not Bower. Some will see this as a disadvantage and others will see it as a strength. You decide, but I like Bower because it’s not opinionated about much.

Using Bower components can be as simple as including a .js file or .css file as traditionally done by front-end developers or as complex as requiring it with something like require.js.

Regardless of how you use components on the front-end, one concept should be honored in most cases. That is, don’t customize local components that are developed by third party developers and installed with Bower. If its in the directory that Bower manages, don’t customize it! Doing so will breakdown the value that Bower is providing as manager of components and their dependencies.

bower.json

Component details are stored in bower.json

The bower.json is a manifest for a component. This file should be placed in a components root directory. It is not necessarily a hard requirement that every Bower endpoint have a bower.json file (or possible, considering url endpoints) to install, but its a must if your component has dependencies.

When creating a component, with the intention of adding to it to the Bower registry a bower.json should always be used. The bower.json file allows a component author to provide critical component details which help Bower do its job.

Below I list all of the available details a component author can provide in a bower.json file.

name [string] - The name of the component. version [string] - A semantic version number (based on semver). main [string|array] - The main files your component provides for users of the component ignore [array]- An array of paths not needed in production that you want Bower to ignore when installing dependencies [object] - Components your component depends upon in production devDependencies [object] - Components your component depends upon during development

Say we are authoring a tooltip component with the intention of adding it to the registry. An example of what a bower.json file might resemble for a tooltip component is shown below:

{
  "name": "tooltip",
  "version": "0.1.0", 
  "main": ["path/to/tooltip.html", "path/to/tooltip.css", "path/to/tooltip.js"],
  "ignore": [".jshintrc","**/*.txt"],
//"latest" is valid value instead of semver
  "dependencies": {"jquery": "latests"},
  "devDependencies": {"qunit": ">1.11.0"}
}

The above tooltip bower.json could have been crafted by hand. But, you should be aware that Bower doesn’t require you to draft bower.json files from scratch. From the command line, in the root directory of a project, the Bower init command can be used to initiate an interactive questionnaire which automates the creation of a bower.json file. This can also be used to update the contents of a current bower.json file. The questions asked during the creation of creating/editing of the file are shown below.

name: 
version: 
main file: 
add current components as dependencies? (y/n): 
add commonly ignored files to ignore list? (y/n): 

I typically prefer authoring these files myself, but using the init command does provide a handy method for creating the file from the command line.

Installing a projects dependencies using a bower.json

The bower.json file can be used at the root level of a project as an installer for project dependencies. Typically, when used in this fashion, it is not exactly the purpose of the bower.json file to represent a component. Imagine you are working on a large project in which you’d like Bower to manage all of the third party components and their dependencies. If a compoent.json file is created with dependency values in a project's root directory, Bower can be leveraged for installing and managing dependencies of all third party code. This gives us the ability to setup application environments for the the front-end with the same ease that typically occurs on the backend (e.g. rubygems, npm, composer). An example of what this file might look like is shown below (Notice the mix use of Bower endpoints).

"dependencies": {
    "jquery": "~1.9.1",
    "lodash": "~1.0.0-rc.3",
    "modernizr-latest": "http://modernizr.com/downloads/modernizr-latest.js",
    "normalize-css": "~2.1.0",
    "string.js": "https://github.com/jprichardson/string.js.git#~1.2.0",
    "js-url": "https://github.com/websanova/js-url.git#~1.7.5",
    "director": "https://github.com/flatiron/director.git#~1.1.10",
    "handlebars.js": "~1.0.8",
    "yepnope": "~1.5.4",
    "font-awesome": "~3.0.2"
}

Imagine if the above bower.json was in the same directory in which bower update was run. This update would download all the dependencies and any sub dependencies.

It is not that uncommon to see a project in Github that leverages Bower for installing code but is itself not intended to be a component. The assumption is that when the repository is cloned Bower is used to install dependencies. These types of projects are typically not ones that would make it into the public registry.

Registering Public Bower Components

We’re not going to actually register a component with Bower, and taint the registry with a fictitious component, but let’s quickly look at how it is done. Before registering a component, you must have a valid bower.json manifest in the root directory and the component must be available from a public Git endpoint and it should use semver Git tags. From the command line, change directories so you are running commands from the root directory the component is located within. To register the component, run the following command.

$ bower register <my-package-name> <git-endpoint>

When registration is complete your component will be available for anyone to consume. It is fairly easy considering you are simply providing a name and endpoint.

Notes:

Conclusion

I wrote this guide because I wanted to lessen the often assumed knowledge required to get started with many of the modern front-end tools dependent on package managers. From here, you should start thinking about how Bower, or tools like Bower, can redefine how internal or external code can be installed and manage on projects. At the very least, I hope this guide has provided the necessary insight required to make use of a package manager and the many tools provided by package managers for use on the front-end.