Managing Frontend Dependencies & Deployment Part 1: Bower

Managing Frontend Dependencies & Deployment Part 1: Bower

Note: This is part one in our Frontend Dependency & Deployment series, read part 2 on Gulp, and part 3 on Yeoman.

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 <davey@engineyard.com>
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 <davey@engineyard.com>",
  "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 <davey@engineyard.com>
[?] 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 <davey@engineyard.com>'
  ],
  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 like public/index.php
  • what types of modules does this package expose? — as we're not building our own libraries, we can skip this
  • set currently installed components as dependencies? — if you install packages by hand using bower install, this will add them as dependencies to your new bower.json
  • add commonly ignored files to ignore list? — this will ignore files and folders that are commonly ignored, such as node_modules, bowers own bower_components, or a tests directory.
  • would you like to mark this package as private which prevents it from being accidentally published to the registry? — answering yes 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?

Note: This is part one in our Frontend Dependency & Deployment series, read part 2 on Gulp, and part 3 on Yeoman.

About Davey Shafik

Davey Shafik is a full time PHP Developer with 12 years experience in PHP and related technologies. A Community Engineer for Engine Yard, he has written three books (so far!), numerous articles and spoken at conferences the globe over.

Davey is best known for his books, the Zend PHP 5 Certification Study Guide and PHP Master: Write Cutting Edge Code, and as the originator of PHP Archive (PHAR) for PHP 5.3.