Expanding Your Toolset: Bower - Package Management For The Web
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 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
ortar
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.
Useful links
Subscribe via RSS