In September, Twitter released Bower, a “package manager for the web”. What does this mean? How is this different from projects like Volo, Ender, and Grunt? Let’s take a look…
A Tiny Little Helper
Bower is small. Very small. The largest file in the repo is only 394 lines and most of the other files clock in around 100, and most importantly, it has a very small feature set.
The only thing Bower does is copy sets of files into the ./components
directory.
Oh sure, it will tell you which sets of files it has copied into ./components
, or make it easier for you to copy new sets of files into ./components
in the future, but Bower is a one-trick pony. This is a good thing.
Bower is easy to understand, so it’s easy for newcomers to pick up, but this doesn’t mean that it’s a toy. The bower ls --map
command provides JSON that can be consumed by higher level tools like Yeoman, making Bower a very UNIXy tool in the modern web developers kit.
Is it like X?
Grunt? Nope. Grunt is a task-based command line tool. It comes with a lot of pre-defined tasks to help you do things like create a bunch of boilerplate code to start a new project, or run JSHint against all your files, or concatenate and minify all your CSS and JS files. Bower doesn’t do any of those things, and Grunt doesn’t want to download arbitrary packages.
Ender? Nope. Ender is a full-featured package manager. Not only does it install packages from the web, it also concatenates and minifies them into a single deployable file. If you want to include a local directory, it still needs a package.json
file. To publish a package, you publish to npm. None of this is too hard, but as we’ll see, it’s about twice as complicated as Bower.
Volo? Nope. Volo is both a task tool and a package manager. It heavily favors AMD modules (no surprise, since it’s written by the creator of RequireJS).
Bower is a minimalist tool that helps you gather files.
Using Bower
Command Overview
Running bower help
shows all the available commands. They fall into four categories:
Get Info on Local Packages
list
, ls
- these are actually just two ways to write the same command. typing either one will show you your current dependency tree
Change Local Packages
install
- install new packages into ./components
uninstall
- remove installed packages from ./components
update
- updating the currently installed packages if new versions are available
Get Info on Remote Packages
lookup
, info
- report information on packages that have been registered with Bower
search
- search the global Bower registry
Change Remote Packages
register
- create a new entry in the Bower registry that will be visible to anyone in the world
Simple Bower
Let’s imagine that you keep a bunch of useful JS helpers in the folder ~/dev/my_library
. If you were inside ~/footest
and ran bower install ~/dev/my_library
, Bower will create a new directory called ~/footest/components
and copy /my_library
inside of it.
You probably won’t use Bower to do local filesystem copies like this very often, but it shows exactly what is going on when you run bower install
. The argument you pass will get copied into ./components
relative to wherever the command is run, creating that subdirectory if necessary.
You can also pass the install
command a http://
or git://
URL instead of a filepath, and Bower will download the file or repo from the URL. However you’ll usually be installing packages that have been registered with the global Bower system. Run bower search
to see all the packages that people have registered, and then run bower install jquery
.
This will create a ~/footest/components/jquery
directory and populate it with a jquery.js
file. WIN! (Make sure you’re in the root of your project when you run bower install
, because it will create the components
directory wherever you run it!)
Bower will also download a component.json
file into /jquery
. This describes the jQuery package. If jQuery declared any dependencies in component.json
, Bower would dutifully go off, download them, and put them in ~/footest/components
as well.
Notice that in our earlier example when we did bower install ~/dev/my_library
, there was no mention of a components.json
file. That’s because Bower doesn’t require one. It’s very happy to just copy over a folder of files. If you have a components.json
in that folder, that’s just a bonus.
So, Bower gives you an incredibly easy way to install packages. Now what? How are you supposed to get them into your web app? Well… The truth is that Bower doesn’t care. You can just use <script>
tags if you want, or you can use a build system like Grunt, Yeoman or the RequireJS optimizer to concatenate your files.
Writing Your Own component.json
You can get even more functionality out of Bower by creating a file called component.json
in the root of your project. Here is a sample from the Bower website:
1 2 3 4 5 6 7 8 |
|
The name and version keys are self explanatory.
The main
key declares the files that the package “exports”, and is used by bower ls --map
and bower ls --path
. (Theoretically, if you are never going to publish your package, and never using a build system that relies on these Bower commands, you could leave main
undefined, but I recommend defining it.)
Dependencies are where the real savings come in. When you run bower install
in the root directory of your project, all the dependencies you declared in your component.json
get installed …and their dependencies …and their dependencies.
Better still, you can lock down which version gets downloaded. Dependencies can be declared as a strict version number such as 1.4.2
or can use comparison operators like >=
.
The ~
operator is extremely useful, because it will look for the latest version after the one specified (like >=
would), but ~
will only bump the least significant part of the version specified. So specifying ~1.4.1
would look for the highest 1.4.x
release. Additional examples can be found in the documentation for ranges in semantic versioning.
If you already have a component.json
file in your project, and you decide that you need to add components, you can save a little time by using the --save
flag with bower install
. This will add an entry for the new component into the dependencies hash inside your project’s components.json
. It only currently works with registered packages, not packages installed via URLs or filepaths.
Publishing Your Component
You, too can create a component that shows up when someone types bower search
. All you have to do is publish your package on GitHub. Then run the bower register
command passing an unregistered name, and the repo’s GitHub URL. Voila!
If you include a component.json
file at the top level of your repo, Bower will install your package’s dependencies for anyone who installs your package. If you don’t include a component.json, Bower will generate one when it installs the package.
Names are first come first serve, so get ‘em while they’re hot!
In Conclusion
I like simple tools. I like Bower.
What’s in a Name
A bower is a house that a bowerbird creates by gathering objects from all over the forest.