I’ve been doing web development for quite a while and certainly the whole development process has a few pains. E.g. making sure the libraries were all up to date, managing dependencies, combining and minifying scripts (or often forgetting to do so). It’s simply a chore that has to be done.

Over the past month a few tools came to my attention that help with chores mentioned above. Those tools are Yeoman, GruntJS and Bower. I’ll go over all three in next few posts, but let’s start with Bower.

What is Bower?

Bower

Bower is a “Package manager for the web”. It was created and opensourced by Twitter.

Installing Bower

Before the installation make sure that you have Git installed, as some packages may require it.

Bower is written in Javascript for NodeJS, so you can install it easily via NPM:

npm install -g bower

-g means that we want Bower to be installed globally. If you don’t want to do that - just remove -g and it will be installed in your current directory.

If you get EACCES errors - prepend sudo to the command:

sudo npm install -g bower

For any other errors consult StackOverflow.

Once that’s done, we’re ready to take a closer look at it.

Using Bower

The great thing about Bower is that it allows you to install packages not only from Bower’s own package registry, but also via other means. As of the day I’m writing this post the list of supported endpoints is:

  • public remote Git repositories
  • private remote Git repositories (supports authentication via https and ssh)
  • local Git repositories
  • public remote Subversion repositories
  • private remote Subversion repositories
  • local Subversion repositories
  • Github repositories (supports shorthand syntax, <owner>/<repo>)
  • URLs to zip or tar archives (contents will be extracted automatically)

Installing the latest version of a package is as simple as running:

bower install <package name>

or if you want a specific version:

bower install <package name>#<version>

If you’re not sure what to install and want to search for packages:

bower search <keyword>

Example

Say we want to install EmberJS. We don’t know how the package is named precisely and do a search run bower search ember. It yields:

$ bower search ember
Search results:

    ember git://github.com/components/ember
    ember-data-shim git://github.com/components/ember-data.git
    ember-data git://github.com/components/ember-data.git
    ember-mocha-adapter git://github.com/teddyzeenny/ember-mocha-adapter.git
    ember-testing-httpRespond git://github.com/trek/ember-testing-httpRespond.git
    ember-addons.bs_for_ember git://github.com/ember-addons/bootstrap-for-ember.git
    ember-model git://github.com/ebryn/ember-model.git

Now we install the ember package with bower install ember. It will go and install ember along with it’s dependencies. You should get something similar to

bower ember#*                   cached git://github.com/components/ember.git#1.3.1
bower ember#*                 validate 1.3.1 against git://github.com/components/ember.git#*
bower ember#*                      new version for git://github.com/components/ember.git#*
bower ember#*                  resolve git://github.com/components/ember.git#*
bower ember#*                 download https://github.com/components/ember/archive/1.4.0.tar.gz
bower ember#*                  extract archive.tar.gz
bower ember#*                 resolved git://github.com/components/ember.git#1.4.0
bower jquery#>= 1.7 <= 2.1      cached git://github.com/jquery/jquery.git#1.10.2
bower jquery#>= 1.7 <= 2.1    validate 1.10.2 against git://github.com/jquery/jquery.git#>= 1.7 <= 2.1
bower handlebars#>= 1.0.0 < 2.0.0           cached git://github.com/components/handlebars.js.git#1.3.0
bower handlebars#>= 1.0.0 < 2.0.0         validate 1.3.0 against git://github.com/components/handlebars.js.git#>= 1.0.0 < 2.0.0
bower jquery#>= 1.7 <= 2.1                     new version for git://github.com/jquery/jquery.git#>= 1.7 <= 2.1
bower jquery#>= 1.7 <= 2.1                 resolve git://github.com/jquery/jquery.git#>= 1.7 <= 2.1
bower jquery#>= 1.7 <= 2.1                download https://github.com/jquery/jquery/archive/2.0.3.tar.gz
bower jquery#>= 1.7 <= 2.1                 extract archive.tar.gz
bower jquery#>= 1.7 <= 2.1                resolved git://github.com/jquery/jquery.git#2.0.3
bower ember#~1.4.0                         install ember#1.4.0
bower handlebars#>= 1.0.0 < 2.0.0          install handlebars#1.3.0
bower jquery#>= 1.7 <= 2.1                 install jquery#2.0.3

ember#1.4.0 app/bower_components/ember
├── handlebars#1.3.0
└── jquery#2.0.3

handlebars#1.3.0 app/bower_components/handlebars

jquery#2.0.3 app/bower_components/jquery

Our new directory structure is:

  % tree -d app
app
└── bower_components
    ├── ember
    ├── handlebars
    │   └── lib
    │       └── handlebars
    └── jquery
        ... SNIP ...

23 directories

As you can see, by default it places all packages in app/bower_components.

Customizing install directory

Say our project has a different directory structure and we want to install packages to js/ instead of app/bower_components. To do that we create a .bowerrc file with a JSON object:

{
    "directory": "js"
}

Now if we install ember again with bower install ember, you should see, that Bower installed it to js directory, just as we told it to:

  % tree -d .
.
└── js
    ├── ember
    ├── handlebars
    │   └── lib
    │       └── handlebars
    └── jquery
    ...Snipped...
23 directories

Automating installation of all dependencies

Say we’re not the only ones working on a project. Let’s assume that we don’t want to commit dependencies to version control. Will other people need to run the exact same commands to install all dependencies our project has? Well, that’s where we’ll create our own package.

A bower package project is defined in file bower.json. (it’s similar to Ruby’s Gemfile or PHP Composer’s composer.json)

You can create the file with bower init and the guide will walk you through all the options, but let’s create this one by hand. Create a new file bower.json with contents:

{
    "name": "test",
    "version": "1.0",
    "dependencies": {
        "ember": "",
        "bootstrap": "~3.1.1",
        "underscore": ""
    }
}

I’ve added a few more packages just to make this example more visual. As you can see the version of the package can be specified as a value of dependencies object. If you omit the version Bower will install the latest one.

Now if we run bower install Bower will install all packages to our install directory (app/bower_components by default, js/ if you’ve left our custom install directory):

  % bower install
  bower bootstrap#~3.1.1      not-cached git://github.com/twbs/bootstrap.git#~3.1.1
  bower bootstrap#~3.1.1         resolve git://github.com/twbs/bootstrap.git#~3.1.1
  bower ember#*                   cached git://github.com/components/ember.git#1.4.0
  bower ember#*                 validate 1.4.0 against git://github.com/components/ember.git#*
  bower underscore#*              cached git://github.com/jashkenas/underscore.git#1.6.0
  bower underscore#*            validate 1.6.0 against git://github.com/jashkenas/underscore.git#*
  bower jquery#>= 1.7 <= 2.1      cached git://github.com/jquery/jquery.git#2.0.3
  bower jquery#>= 1.7 <= 2.1    validate 2.0.3 against git://github.com/jquery/jquery.git#>= 1.7 <= 2.1
  bower handlebars#>= 1.0.0 < 2.0.0           cached git://github.com/components/handlebars.js.git#1.3.0
  bower handlebars#>= 1.0.0 < 2.0.0         validate 1.3.0 against git://github.com/components/handlebars.js.git#>= 1.0.0 < 2.0.0
  bower bootstrap#~3.1.1                    download https://github.com/twbs/bootstrap/archive/v3.1.1.tar.gz
  bower bootstrap#~3.1.1                     extract archive.tar.gz
  bower bootstrap#~3.1.1                    resolved git://github.com/twbs/bootstrap.git#3.1.1
  bower jquery#>= 1.9.0                       cached git://github.com/jquery/jquery.git#2.1.0
  bower jquery#>= 1.9.0                     validate 2.1.0 against git://github.com/jquery/jquery.git#>= 1.9.0
  bower ember#*                              install ember#1.4.0
  bower underscore#*                         install underscore#1.6.0
  bower jquery#>= 1.7 <= 2.1                 install jquery#2.0.3
  bower handlebars#>= 1.0.0 < 2.0.0          install handlebars#1.3.0
  bower bootstrap#~3.1.1                     install bootstrap#3.1.1

  ember#1.4.0 js/ember
  ├── handlebars#1.3.0
  └── jquery#2.0.3

  underscore#1.6.0 js/underscore

  jquery#2.0.3 js/jquery

  handlebars#1.3.0 js/handlebars

  bootstrap#3.1.1 js/bootstrap
  └── jquery#2.0.3

bower install will also install any missing dependencies, so if we “accidentally” remove a package and then run bower install, we should see the missing dependency installed again:

  % rm -rf js/underscore
  % bower install
bower underscore#*              cached git://github.com/jashkenas/underscore.git#1.6.0
bower underscore#*            validate 1.6.0 against git://github.com/jashkenas/underscore.git#*
bower underscore#*             install underscore#1.6.0

underscore#1.6.0 js/underscore

And lastly, if you want to update packages, use bower update.

Last thoughts

So far I really enjoy using Bower. I’m excited that it makes one more web development pain go away, but I suspect it will have a larger impact once we start using Bower in combination with GruntJS and Yeoman. I will cover those in next few posts, so that’s it for today.