Bower: Best served with a build toolClosing the package management loop with a build tool
Bower was created and released by Twitter in 2012, part of a open-source movement that the company undertakes. Like
npm for Node.js and
gem for Rails, Bower aims to be the package manager for the web.
Bower does well in solving certain aspect of package management such as fetching and installing package, checking of package dependencies and compatibility, etc. But those does not make up the complete chain of package management.
My ideal package manager can install and inject my required packages in the right order with the correct file path reference automatically.
To reach that state, I will need a help of a build tool. Ok, let's start with a simple use-case - Include jQuery and jquery.hammer.js in your website
The traditional package installation usually goes like this:
- Go to the jQuery website
- Download the jQuery file (version 1.11.1) to the download directory
- Copy and paste the jQuery file to the working directory
- Manually reference the jQuery file in the correct order inside your working file (eg.
- Next, to install jquery.hammer.js, repeat Step 1 - 4
- You realise jquery-hammer depends on jQuery 2.0. Repeat Step 1 - 4 to install the correct jQuery version.
The Pain of Package Management
With the above flow for package installation, a developer used up a good part of his cognitive load before he starts developing:
- Discovery of packages - Where to download the plugin?
- Checking of package dependencies - What other libraries I need to make my plugin work?
- Compatibility of packages - Will my package be affected by other packages?
- Ordering of package referencing - Which files should I include first?
- Manually finding the correct files within the package - Which file/s in these entire package is/are the right file to import into my project
- Manual reference to the individual file path which introduces potential typo error - Did I type the right file path?
These pain will scale in magnitude as the website gets more complicated and the amount of packages increase.
It's Bower Time
Let's use Bower to tackle the aforementioned problems.
With Bower globally installed:
- Install jQuery:
bower install jquery#1.11.1
bower install jquery-hammerjs
Bower prompts error and ask me to pick my preferred version. If 2.0 is selected, the jQuery library will be auto-updated.
Manually reference the jquery.hammer.js file and its dependencies in the correct order inside the working file.
Bower downloads the libraries and dependencies straight into my working directory. It also checks for and resolves compatibility issues. But that's about it. Bower managed to solve problem (1) - (3), leaving problem (4) - (6) intact.
Build Tool takes the wheel!
Bower is an un-opinionated package manager. It allows free play on the integration of bower into your current workflow and tooling by providing the developers with a manifest file (bower.json), configuration file (.bowerrc) and hooks.
Let's take a look at bootstrap's bower.json:
We shall focus on two important options:
main option can take in a string or array. It declares the necessary files to use the package. The
dependencies options declares the package dependencies.
The npm package that I had selected,
grunt-wiredep, takes advantage of these configurations to wire up the dependencies and installation.
Grunt, I choose you!
I will be using Grunt but other build tools like Gulp or Broccoli are suitable too.
My working directory is simple. It just has a index.html in it. Follow the steps below to prepare your working directory for awesome package management. Make sure your npm, grunt and bower are installed.
- At the root of the working directory, setup the package.json:
- Setup the bower.json:
- Install grunt-wiredep and matchdep npm package:
npm install --save grunt-wiredep && npm install --save matchdep
Create a Gruntfile.js in your working directory
Insert the placeholder in your index.html
Now that your directory is prepared, you are ready to install your packages.
bower install -S jquery-hammerjs
grunt-wiredep, the files are ordered automatically and inserted into the index.html with the correct file path reference. This effectively solve problem (4) - (6).
Let's try installing bootstrap.
bower install -S bootstrap
We live in a imperfect world
For the build tool to work effectively, every package must have the
dependencies stated accurately by the package owner. However in the real world, you will bound to come across packages that have missing or incorrect
dependencies options. All is not lost though. You can override those missing options with
grunt-wiredep, using the
Look out, ZSH users!
Initially, I wasn't able to install specific package version by
bower install <package>#<version>. I keep getting this error:
no matches found.
After some googling, I found that my shell, ZSH, was the problem.
You can fix it with
alias bower='noglob bower'.
I'm beginning to use Bower, combined with Grunt, for all small and large projects. The ability to grab libraries off the command line and immediately start development is an empowering feeling. Those days of manual fetching and installation packages seems long gone.