Creating and maintaining your own Bower package

Bower logo A package manager for the web. Bower is a nice utility for managing your projects client-side dependencies. If you're a web developer, you've probably at least heard of it, and maybe you've even used it to consume and manage the packages you use in your web app. You might have also thought to yourself, I wonder what I would need to do to share <that awesome little client library of yours> with the world through Bower. Well I'm hoping with this article I might be able to help with that.

First things first

Before doing anything, there are two foundational things that I feel are key to understanding how to effectively distribute your package through Bower:

  1. Bower is built on top of git. You can't distribute your package through Bower without it being hosted at some git endpoint, whether that is at GitHub, Bitbucket or some other git hosting provider (maybe you host your own). Effectively, when you register a package with Bower, you're telling it where it can access the contents of your package when consumers request to install it, and which contents of your repository you want distributed to package consumers. For the purposes of this article, I will be using GitHub as an endpoint for reference.
  2. Package versions are just git tags. We'll discuss this in more detail shortly, but effectively you need to know that making a new "release" of your package available in Bower is as simple as tagging a changeset in your git repository.

OK, now that that's out of the way...

Package Contents

The first thing you'll need to do is configure your package to be able to work with Bower. This is as simple as adding a bower.json file to your project. In its simplest form, it might look something like this:

{
    "name": "YourAwesomePackageName",
    "version": "0.0.1"
}

I'm actually not even certain that the version attribute is required, but eventually you'll need it to register your package, so its a good idea to have it in there. Of course, that's a very simplistic example, and there are a few other things that I prefer to have in there. If you register your package with the above bower.json file, when a consumer installs your package via Bower, it will download your project's entire git repository into their project. You don't really need or want that, do you?? No, I didn't think so.

In my humble opinion...

When I'm consuming your Bower package, I don't need and really don't want your entire project directory structure downloaded into my project's directory structure. So, when I create my Bower packages, I like to make liberal use of the ignore attribute in my bower.json file.

ignore [array]: An array of paths not needed in production that you want Bower to ignore when installing your package.

This basically tells Bower: hey, when someone installs this package, ignore this stuff and don't distribute it to 'em, OK?...cool, thanks. Now, when I create packages like this, they typically end up being just a single JavaScript module...maybe a default stylesheet...you might have some images too, who knows. Ultimately though, my general rule of thumb is, just distribute what consumers need to be able to use your package...not all of your development dependencies, test suite, documentation, etc, etc.

That being said, for a package with a single JavaScript module, I would typically have a build script that generates that module into a dist folder, one thats minified, and one thats not. For such a project, the bower.json file would end up looking something like this:

{
    "name": "YourAwesomePackageName",
    "version": "0.0.1",
    "main": "dist/your-awesome-js-module.js",
    "ignore": [
        "source",
        "spec",
        ".bowerrc",
        ".gitignore",
        ".jshintignore",
        ".jshintrc",
        "bower.json",
        "gruntfile.js",
        "package.json",
        "README.md"
    ],
    "dependencies": {
        "jquery": ">=1.10.2",
        "underscore": "~1.5.2"
    },
    "devDependencies": {
        "jquery-mockjax": "~1.5.2"
    }
}

So you'll notice that I'm not telling it what to include in the distribution (although, an option like that would be NICE...hint hint), but I'm effectively telling it to ignore everything except my dist folder. Also notice that my package depends on both jQuery and underscore.js...Bower will pull those in for consumers when they install this package as well. THAT is exactly the kind of thing that makes Bower nice...you don't have to download my package and jQuery and underscore.js from their respective web sites as well.

So thats it. Setup a bower.json file in your project, and check it all in to your git repository. Once you've done that, then you just need to register it...

Registering your package with Bower

The bulk of the work was in that last section. Getting your package registered is actually pretty simple. However, One important thing to remember before registering your package...as I mentioned earlier, git tags are your packages versions...so before you initially register your package, its a good idea to remember to tag your package repository with a version number. Also, after you've tagged it, don't forget to push that tag to your repository remote with the --tags switch...its easy to forget to do that part.

With that out of the way, you're almost there...now for the easy part. Just execute the following Bower command at a terminal prompt:

NOTE: This may go without saying, but just in case, all of this assumes that you have the Bower NPM package installed...

bower register YourAwesomePackageName git://github.com/yourGitHubUsername/YourAwesomePackageName.git  

As I mentioned previously, I'm using a GitHub endpoint for reference here, but you could use any git endpoint to register your package with.

What...expecting something more? Nope. That's all there is to it. Now your package is registered with Bower. Now if you go back to that same terminal prompt and run:

bower info YourAwesomePackageName  

You should see something like this:

bower cached        git://github.com/yourGitHubUsername/YourAwesomePackageName.git#0.0.1  
bower validate      0.0.1 against git://github.com/yourGitHubUsername/YourAwesomePackageName.git#*  
bower new           version for git://github.com/yourGitHubUsername/YourAwesomePackageName.git#*  
bower resolve       git://github.com/yourGitHubUsername/YourAwesomePackageName.git#*  
bower download      https://github.com/yourGitHubUsername/YourAwesomePackageName/archive/v0.0.1.tar.gz  
bower extract       YourAwesomePackageName#* archive.tar.gz  
bower resolved      git://github.com/yourGitHubUsername/YourAwesomePackageName.git#0.0.1

{
  name: 'YourAwesomePackageName',
  version: '0.0.1',
  main: 'dist/your-awesome-js-module.js',
  ignore: [
    'source',
    'spec',
    '.bowerrc',
    '.gitignore',
    '.jshintignore',
    '.jshintrc',
    'bower.json',
    'gruntfile.js',
    'package.json',
    'README.md'
  ],
  dependencies: {
    jquery: '>=1.10.2',
    underscore: '~1.5.2'
  },
  devDependencies: {
    'jquery-mockjax': '~1.5.2'
  },
  homepage: 'https://github.com/yourGitHubUsername/YourAwesomePackageName'
}

Available versions:  
  - 0.0.1

You can request info for a specific version with 'bower info YourAwesomePackageName#<version>'  

If you do, then you're golden. Now your package is available for the world to use and enjoy. Nice!

Updating and maintenance

Because we all know that nobody ever writes the perfect, defect-free module/package straight out-of-the-gate, there will undoubtedly come some point at which you will make some updates to your package and will need to update the Bower registry with those updates, right?

Well, actually, that's another nice thing about Bower. There is never any need to make any updates to your package registration in Bower. As I mentioned earlier, Bower relies solely on information it gets from git about your package. The process for updating your package will involve three primary steps:

  1. Make the necessary changes to your package artifact(s) (bug fixes, new features, etc, etc...whatever it might be)
  2. Update your bower.json file with the new version for the package
  3. Commit your changes, tag the repository and push your changes to git (don't forget to include the --tags switch with your push command to your remote!)

There's a couple of important things to notice here. As I mentioned previously, Bower relies solely on git tags for package version information. This means that in order to "release" a new "version" of your package, you have only to create a new tag in your repository with the new version number for the update. Its important to be sure to update the version number in your bower.json file accordingly as well. With those changes pushed to your package repository in git, you're good-to-go.

So to summarize that: make the desired changes to your package, update the version number in your bower.json file (maybe version 0.0.2 now), and commit, tag and push the changes to git:

# commit your changes
git commit -am "Made some awesome new changes, now its even awesomer"

# tag the commit
git tag -a v0.0.2 -m "Release version 0.0.2"

# push to GitHub
git push origin master --tags  

There are a couple of options that can help simplify this process a little bit too...

GitHub Releases

If you are using GitHub as your git provider, they recently released a new feature called "Releases" (read about them here). Releases can help simplify this process a little bit by giving you a nice, easy-to-use, web-based interface on your GitHub repository for tagging and documenting a release. If you would prefer to use this feature, in order to release a new version of your package for Bower, you would just need to make the necessary changes, commit and push to GitHub, and then use the GitHub interface to create a Release. This may be a simpler workflow for some who might prefer it. At very least, its another nice option to have.

Grunt Bump

If you use Grunt to build your package, there is a nice plugin for it called grunt-bump that can help with automating the process of updating the version number in your bower.json file and automatically tagging your committed changes. It will even go so far as to push your changes up to GitHub for you too if you so desire. The thing I like most about this plugin is how flexible it is. For example, the default functionality of the plugin commits your changes, creates a tag and pushes the commits and tags to git for you. This goes a little bit further than I would prefer, so I was able to customize this task in my grunt script like this:

bump: {  
    scripts: {
        files: ["source/*.js", "spec/*.js"],
        updateConfigs: ["pkg"],
        commitFiles: ["-a"],
        push: false
    }
}

This effectively gives me a nice, comfortable workflow in which I can make the desired changes to my package and commit those changes. Then, when its ready for release, I can run:

grunt bump  

...at a terminal prompt, and that will take care of automatically incrementing the minor version number of my package for me in both my package.json and bower.json, commit the changes to those files, and create a tag with the new version number as well...without pushing those changes to git for me, which I prefer to do manually.


If this is something that was of interest to you, I hope it was helpful. If it was, and you now see how simple it is to create, register and maintain your own Bower package, I fully expect to start seeing a lot more awesome available in the Bower registery. No more excuses!! *grin*

All comments and feedback are welcome.


CREDITS: Many thanks again to Ryan Niemeyer for his review and valuable feedback on this article.