Manage internal front-end dependencies with Bower

Maintaining giant, monolithic codebases is basically impossible which is why most programmers break larger codebases into smaller ones and try to manage them separately. Breaking things out into the controlling code and its dependencies is a common and smart pattern but a lot of people do this two different ways: For external dependencies we use a management program like Bundlr, NPM, or Bower. But for internal dependencies we use nothing. Why bother? Afterall, we already control the code so why not just stick it straight into the repo with the rest of the javascript? Of course we're still a little careful so instead of installing it in /assets/javascripts/ we put it in /assets/javascripts/vendor.

This is a problem both in reasoning and implementation. We use a package manager not just to retrieve libraries but also to version them and keep track of what we do and do not need in our repos. The same thing applies to internal dependencies; We still need to version them and manage what can be eliminated when we're no longer using it. We know that software versioning is !important, otherwise we wouldn't be keeping it in a git repository. People even go to great lengths discussing how to version the software.

To make this problem a little bit easier, I like to use Bower. I could also use NPM but that's more for server-side stuff. Or I could use git submodules but those are harder to set up and I think they're better suited to code that needs to have a parent as opposed to utility libraries and the such.

It's easy to use in your codebase

Just run the following in your terminal, answer a few questions and you're all set to start requiring your dependencies:

npm install -g bower  
bower init  

Then it's as easy as bower install --save my-dep.

It works with your private repos

I think the largest concern with using a package manager for internal dependencies is whether it will expose your sensitive or proprietary code to the public. Bower gives us a couple of tools for that. The first is that you can tell Bower not to accidentally publish your code. In your bower.json file set private to true:

{
    "name": "myModule",
    "version": "1.1.0",
    ...
    "private": true,
    ...
}

The other great thing is that it works with private repos and can retrieve code directly without having to go through the registry. Just define a git endpoint for your repository as a dependency:

{
    "name": "myModule",
    "version": "1.1.0",
    "dependencies": {
        "privatedep": "git@corporate.com:projects/privatedep.git#2.3.1"
    },
    ...
}

Make sure to use that user@ ... .git syntax or Bower will try to look in the registry which will not work.

It's easy to add to your dependencies

This should be super simple. cd into your repository directory, run bower init to create the bower.json file and then git commit and git tag with your current version number. Push your changes up to your host and your projects can now requires that dependency through Bower. It takes about a couple minutes per dependency.

It's now easy to version your software with or without Bower

Once you start using a lot of management tools, you start to run into a particular issue where you have way too many config files(package.json, component.json, CI.json, bower.json...) and keeping the version number synched up between them gets to be a bit of a pain. My current favorite solution to this is grunt-bump. It provides a simple grunt config where you can tell it how to behave and what files it needs to update and then bumping your version number is as simple as grunt bump if you want a patch version or grunt bump:major for a major version.

Bower gives us testing superpowers!

If you've made changes to a dependency that you want to test with your higher-level repo, sometimes you want to run those tests before you merge the changes into master. With Bower, you can point your dependencies at a particular tag or branch so you can test your changes in a feature branch first. Change your bower.json file and update the part after the hash in the repo name to your branch name you want to test:

{
  ...
  "dependencies": {
    "mydep": "git@example.com:myteam/mydep.git#testing-branch"
  }
}

Now you can test away without having to merge into master or create a new tag!