Client-side development has been shifting away from monolithic libraries. While jQuery is still hugely popular, building projects from smaller libraries is increasingly common. To make this easier to deal with, projects have appeared to manage dependencies. These tools may be simple package managers, or a combination of a build tool and a package manager.
Client-side package managers have been around for a few years now. An earlier example is CPM, which is a CommonJS package manager. Last year the subject got newfound attention from Node developers. There was a very public debate between Isaac Schlueter and TJ Holowaychuk in which several issues were covered:
What isn't immediately obvious about Component is it builds client-side scripts by adding a CommonJS Modules/1.1 implementation -- components are loaded using
var lib = require('lib'). The upshot of this is there's a learning curve to writing components, and also understanding how to make this work inside existing projects. Component is specifically designed to work regardless of server-side architecture, so you could use it with Django, Express, or Rails projects without special handling. Discovering how to use components inside these frameworks is the main point of friction when switching to a component-based workflow -- do you structure your entire project around components? Or just use Component as a way of managing dependencies?
Contrast this to Bower. It's more like earlier projects, which include Jam and Volo, and therefore offers less in terms of treating entire slices of the UI as reusable chunks. This is by design -- Bower is meant to work with build tools rather than replace them.
Then there's Ender, which provides an API for loading modules (CommonJS is supported), and is built on top of npm. Jam encourages the use of AMD and depends on RequireJS. Volo doesn't depend on AMD modules, but encourages them to be used.
Bower could have effectively been:
curl http://wherever-bower-repos-are.com | grep underscore | xargs git clone
That's how I initially felt when I first saw Bower, but Bower's simplicity is a result of it being designed to work alongside client-side build tools. That means Bower will work with RequireJS, LoadBuilder, or even Sprockets. If you're using a large server-side framework like Rails, then it might be easier to use Bower with the framework's existing asset management tools.
As TJ hinted at above, the biggest problem facing client-side package managers is anybody can make one. It doesn't take much effort to write a script that can fetch libraries from GitHub and then pipe them through UglifyJS.
Bower's separation between package manager and build tools is insightful, but I also think the modular client-side development being pushed by Component is extremely important and makes client-side development better.
We're now at the point where library authors are increasingly including a
component.json file. How do you know if this is a Bower or Component manifest file? Let's say I want to install pjax. It has a
component.json, so I run
component install defunkt/jquery-pjax. The result is an error:
error : Error: invalid component name "jquery"
It turns out pjax is designed to be used with Bower.
This situation is made more confusing because neither project addresses this fact. It's almost like they don't want to acknowledge each other. There's a discussion about Bower in the component Google Group, but neither project is particularly helpful with regard to the differences between manifest files, given the decision to use the same name.
Is Bower run by evil Twitter imperialists hell-bent on wrestling
component.json away from the Component project? Well, no, because Bower can be configured to use a different file name, and the projects have different goals. However, the clash is unfortunate, particularly for client-side developers who work closer to the design end of the design/coding spectrum, and may not even be aware that both projects exist.
|Appeared||Sep 2012||Aug 2012||Apr 2011||May 2012||Oct 2010|
|Module Pattern||CommonJS||CommonJS||AMD||AMD/CommonJS compatible|