Choosing Between npm, Bower and component

package_mgmt_header

By Seth Vincent

There is still no best answer to client-side package managers and dependency management. We still have to cobble together the solutions that work best in the context of each project, but at least we’re not downloading js/css manually through the browser, using wget or writing bash scripts to download/update our client-side dependencies.

We have better options.

In this article I will focus on three that fit best with my development workflow and discuss my personal strategy for when and how to use them:

All three are quite different:

npm

npm nominally started out as a package manager for Node.js but can be used for any JavaScript. Along with a tool like browserify, it’s easy to use npm packages and Node-style modules in the browser. It’s not super useful for CSS libraries – but it’s easy to imagine a tool (built on something like brfs) that could make bundling CSS npm packages very pleasant.

You install npm by installing node. Packages are installed using npm install <package name>.

Example:

npm install --save request

The optional --save option adds the package as a dependency to the project’s package.json file. You can create a package.json file using the npm init command.

Bower

Bower is a hero of client-side code: it’s great for both CSS and JavaScript. It’s easy to manage dependencies, even if those dependencies don’t have a config file for Bower. You can install a file or Git repository as a dependency alongside packages in the Bower registry. Bower doesn’t make any assumptions about how you build or deploy code, so it is compatible with AMD modules.

Bower is distributed as an npm package, so install it with: npm install -g bower

The -g option installs the Bower package globally and exposes the bower command. Packages are then installed like this:

bower install --save <package name>

The optional --save option adds the package as a dependency in the project’s bower.json file. If a bower.json doesn’t already exist, you can create one with the bower init command.

component

component is a tool with a more focused and defined goal for front-end code than npm and Bower. It uses CommonJS style modules. Each component may contain JavaScript, CSS, fonts and images. Some JavaScript-only components can also be used in Node.js. See the component FAQ for more details.

component is also installed using npm:

npm install -g component

The syntax of the component command is a little different. It relies on GitHub repositories and uses the same namespace, so a package is identified by a /.

Installing looks like this:

component install <username>/<package name>

For example:

component install component/dom

The above command installs the dom component, which is a collection of small components that replicate the functionality of jQuery.

To add dependencies to component.json, you can use the component-set command.

You can learn more about component here: https://github.com/component/component

When I use npm for browser code

Games. There’s been a lot of interesting activity in JavaScript game development in the Node.js community using browserify. voxel.js is one of the biggest examples, with a goal of creating Minecraft-like games in the browser. For more examples, check out this wiki of game-related modules and projects that use Node, npm and browserify: https://github.com/hughsk/game-modules

npm and browserify are be useful for creating applications that might share JavaScript code on the server and the browser. This approach also works well when the JavaScript requirements for the client-side are minimal, or if you prefer to write client-side code in a Node style.

If I’m using npm and browserify, I’m almost always using beefy as the live-reload development server. It’s great.

I sketch ideas in requirebin.com sometimes. It’s a pretty great little service that let’s you require modules from npm, run them through browserif, and view the results of that code – all in the browser.

You can learn more about npm at npmjs.org

When I use Bower for browser code

When the project requires a front-end framework like Backbone or Angular, I use Bower as the package manager. It’s currently the best way to package the arbitrary dependencies of a JavaScript application. It’s possible to use Backbone and jQuery with browserify, but so far that hasn’t made sense for me yet.

Typically using Bower means that I am also using the Grunt build tool and its associated plugins as the live-reload development server as well as for packaging builds and any other task automation.

To learn more about Bower, visit bower.io.

I don’t really use component yet…

…but I definitely want to. It looks like there’s some great work happening around component. I expect that there will be instances when I’ll want to use some of the available components. Many components have Node.js support and should just fit into my usual npm/browserify workflow without issue. However, I would likely be installing those components via npm rather than the component command.

Use all three at once!

Check out this great guide for using components, bower packages, AMD modules and even global variables with browserify: Browserify and the universal module definition

This article is part of learnjs e-book guide to building projects with JavaScript and was originally published at http://superbigtree.tumblr.com/post/58075340096/my-strategy-for-client-side-package-managers-choosing

15 Comments

  1. Raymond Camden said:

    My problem with bower is that even for something as simple as jQuery, you get a huge amount of files. What I want is a tool that gets jquery.js. That’s it. Nothing more. I don’t need the metadata as I won’t be updating the library. Don’t get me wrong – I get that Bower is powerful, but 90% of the time for me I need to get the JS/CSS for a library one time and that’s it. Even with Bower I still have to go into the folder it downloaded and grab just the bits I need.

  2. Sebastian Porto said:

    Tried Bower for a while but found it very inconsistent. Some libraries will download just development files, not ‘compiled’ js file to be found that can be linked to. Bower needs to enforce some best practices to be really useful.

  3. Marco Oliveira said:

    For Raymond and Sebastian, I think you’re missing the point with Bower. Even though what you said has a point, keep in mind that what you complained about was the fact that other developers are not following “the way I think people should distribute components”. Note that this will most likely for a long, long time always be the truth. Even when this changes, there is no guarantee you will be left with your own personal way of seeing components. That heavily depends on how the component is built, if it is AMD based, and what the author thinks is the best way to distribute. Instead, Bower is more practical, and allows you to use pretty much any kind of component, indeed solving a real world problem. Also, if you haven’t tried Bower lately, I recommend that you do, as it has evolved significantly. Good stuff ;)

    • Sequoia said:

      I think it’s fair to say frontend library distributions shouldn’t require a server build step, or at least that it should be simple (e.g. bower build). Npm even throws warning if you don’t have a readme… build tools can specify (overrideable) requirements for packages, most do.

      • Martin Wawrusch said:

        It took npm a long time to get there, and it started out when there were almost no node.js modules. Bower on the other hand has to deal with a wide variety of pre existing libraries. For that it does a great job, to the point where we try not to use modules that aren’t listed in bower.

        • Marco Oliveira said:

          Exactly :) Baby steps. Maybe one day, with wide adoption, we’ll be able to impose some standards upon publishing packages.

  4. Tim Branyen said:

    I help maintain JamJS, a relatively dead package manager. One of the best features I found using it is that upon installing a package `jam install d3`. I could immediately import the package using whatever style (CommonJS,AMD,ES6,etc.). It just didn’t get widespread enough appeal due to it’s RequireJS dependency.

  5. TJ said:

    The thing with Component (or npm) is that you can have real dependency trees: https://dsz91cxz97a03.cloudfront.net/ODBOYFp2qA-2000×2000.png

    You could attempt to do this with Bower but it would be hell. Bower modules are much more like traditional JavaScript libraries, so it’s good if you want to re-use a lot of things, not good if you want to use/write good code. Npm is a contender but there’s no formal way of describing anything other than JavaScript.

    • Vladimir Varankin said:

      Have seen BEM methodology (bem.info) which was build to create (and maintane) re-useable web-components, which could consist of a lot of technologies like CSS, client/server-side JavaScript etc.

      BEM as a methodology actualy solves the same problems as Components but was developed at Yandex (yandex.ru) long time but for now it has rather big OpenSource communite in a Front-End world :)

    • Marco Oliveira said:

      Actually, that specific case is really simple. You would declare the dependencies in the bower.json just like you’re used to declare on package.json, and bower takes care of the rest. Conceptually, there is a dependency tree. How that is mapped to the filesystem is another issue completely. The hypothesis you gave is only valid when you have multiple common dependencies with incompatible versions. And even that is only a problem if the packages are relying on the global scope. If they use CommonJS or AMD you will get the exact same behaviour as with node.js and require().

  6. Fazal said:

    There are so many tools out there, it’s great to see so many projects tackling the problem. Ultimately, most developers will settle on one, and will become the defacto standard for apps and websites respectively.

    One such project that has caught my attention recently is http://jamjs.org/ which is purely a JavaScript package manager.

  7. Toby Ho said:

    Seth,

    Thanks for the run-down. You mentioned that using browserify with frontend (jquery and backbone) hasn’t made sense for you. Specifically why do you think this is? I am interested knowing whether this is a fundamental design issue or something that can be fixed on the browserify side.

*

*

Top