Managing Frontend Dependencies & Deployment Part 1: Bower
In PHP we have composer
, in Ruby we have bundler
, and Node.js has npm
for managing our application dependencies. Be they packages, or gems, these tools are improving our development workflows immensely.
These package managers allow us to create de-facto standards-based workflows that assist in the development and deployment of our applications.
That’s all well and good for our PHP, Ruby, and Node.js… but what about our frontend?
Increasingly we’re turning to libraries like jQuery, Angular.js, Bootstrap, Foundation, and all the multitudes of plugins that go with them. We typically end up manually managing both the libraries — via submodules, or usually just downloading zip files and unpacking them — and dependencies by hand (usually by trial and error).
Bower
There is a solution, Bower. Bower — like Bootstrap before it — comes from the folks at Twitter, and is “a package manager for the web”.
Installing Bower
Installing Bower is easy. Assuming you already have node.js and npm installed (see here for information), first init our project by creating an npm package.json
using:
$ npm init
name: (gulp-bower-example)
version: (0.0.0) 0.0.1
description:
entry point: (index.js) public/index.php
test command:
git repository:
keywords:
author: Davey Shafik <[email protected]>
license: (ISC) Apache 2.0
About to write to <path>/gulp-bower-example/package.json:
{
"name": "gulp-bower-example",
"version": "0.0.1",
"description": "",
"main": "public/index.php",
"dependencies": {
"bower": "~1.3.5"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Davey Shafik <[email protected]>",
"license": "Apache 2.0"
}
Is this ok? (yes)
All of the necessary prompts should be self-explanatory, you can skip the rest.
Next you can install Bower:
$ npm install -g bower
This will make the bower
command available globally.
To make it install locally, and automatically, with npm install
, additionally run:
$ npm install --save-dev bower
This installs it to ./node_modules/bower
, with the bower
command available at ./node_modules/.bin/bower
. To add this directory to your path automatically, npm
includes a bin
sub-command that will return the path to this directory no matter where you are in the project, so simply add $(npm bin)
to your path, or you can use an alias like so:
alias npm-exec='PATH=$(npm bin):$PATH'
Now you can run either bower
and it will pick up the correct one (local if it exists, or global otherwise) or if you used the alias, you can use npm-exec bower
.
Using Bower
Similar to other package managers, Bower uses the bower.json
file to setup dependencies.
Like both Composer and NPM, Bower will treat every project as an installable library in its own right. This means whether you just want to use Bower to manage your dependencies, or are writing your own libraries, the setup is very much the same.
$ bower init
[?] name: gulp-bower-example
[?] version: 0.0.1
[?] description:
[?] main file: public/index.php
[?] what types of modules does this package expose?
[?] keywords:
[?] authors: Davey Shafik <[email protected]>
[?] license: Apache 2.0
[?] homepage:
[?] set currently installed components as dependencies? Yes
[?] add commonly ignored files to ignore list? Yes
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry? Yes
{
name: 'gulp-bower-example',
version: '0.0.1',
authors: [
'Davey Shafik <[email protected]>'
],
main: 'public/index.php',
license: 'Apache 2.0',
private: true,
ignore: [
'**/.*',
'node_modules',
'bower_components',
'test',
'tests'
]
}
[?] Looks good? Yes
This will walk you through numerous questions to generate a new bower.json
file. Some of the questions are pretty obvious, while others may be a little confusing:
main file
— this would be the entry point for the application, in the case of PHP that’s likely something likepublic/index.php
what types of modules does this package expose?
— as we’re not building our own libraries, we can skip thisset currently installed components as dependencies?
— if you install packages by hand usingbower install
, this will add them as dependencies to your newbower.json
add commonly ignored files to ignore list?
— this will ignore files and folders that are commonly ignored, such asnode_modules
, bowers ownbower_components
, or atests
directory.would you like to mark this package as private
which prevents it from being accidentally
published to the registry?
— answeringyes
will stop you from being able to accidentally publish your “package” to the bower registry.
At this point, you can easily now install packages, updating the bower.json
along the way:
$ bower install --save jquery bootstrap
This will install the latest jquery and bootstrap into the bower_components
directory. If you check your bower.json
, it will have been updated with:
"dependencies": {
"jquery": "~2.1.1",
"bootstrap": "~3.1.1"
}
Now, if we wanted to install these dependencies in a fresh checkout, we can simply run:
$ bower install
If webroot isn’t the root of your project (which it likely isn’t), you can easily change the install directory by creating a new file .bowerrc
with the following:
{
"directory": "public/bower_components"
}
Once you’ve done this, delete the original install, and install again:
$ rm -Rf bower_components
$ bower install
You can then reference the files as /bower_components/<package>/dist/<files>
for example to include Bootstrap you would add the following two lines in their appropriate places:
<link href="/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/bower_components/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet">
<script type="text/javascript" src="/bower_components/bootstrap/dist/js/bootstrap.min.js">
To keep your libraries up-to-date simply use bower update
:
$ bower update bootstrap
Taking Control
Bower gives us complete control over the installation and management of our libraries and their dependencies — in a way that is easily tracked in revision control, and easily distributable within a team using bower.json
and bower install
.
Now that we have our dependencies under control, versioned and kept up-to-date, what about deployment?
In the next part in this series we will look at how we can work with these bower components both in development and deployment.
Are you already using Bower? We’d love to hear from you about how it fits into your workflow, and if you’re not using it, why not?
Share your thoughts with @engineyard on Twitter