This article was written in 2014, when npm 2 was the latest, and wasn’t popular among fronted developers because of the issues described in the article. Now use Yarn or npm, and consider this article historical.
This article was first published in the May 2014 issue of Russian “Hacker” magazine. The article in the magazine is a shortened version; the full one is below. Article was translated by George Gritsouk for Frontend Babel.
Package managers simplify installing and updating project dependencies, which are libraries that it uses: jQuery, Fotorama, everything that is used on your site and isn’t written by you.
Browsing all the library sites, downloading and unpacking the archives, copying files into the projects—all of this is replaced with a few commands in the terminal.
Bower doesn’t prescribe to the user its own build tool, or to the developer a method of including libraries (AMD, CommonJS, etc.) All Bower does is install the right versions of the packages that the project needs and their dependencies. In other words: it downloads source files for the right libraries and everything they need into a special folder. Everything else is up to the developer.
Why not npm
The main difference between npm and Bower is the approach for installing package dependencies. npm installs dependencies for each package separately, and as a result makes a big package dependency tree (
bower_components/jquery folder, regardless of how many packages depend on it) and in the case of a dependency conflict, Bower simply won’t install the package incompatible with one that’s already installed.
To work with Bower you’ll need Node and git. Installation:
npm install -g bower
Working with packages
Let’s try to install something, for example jQuery:
bower install --save jquery
This command will download the latest version of jQuery into the
--save flag tells Bower that it should save the package name and its version into the
bower.json manifest file. In this file is a list of all dependencies of the project (packages installed with Bower) and other metadata required for creation of your own packages (more on this at the end of the article). With the package names it’s possible to specify the version with which your project is guaranteed to work.
We don’t have a file like that yet, which is what the line “No bower.json file to save to, use bower init to create one” in the log is about. Let’s create it:
Bower will ask many questions, but until we want to register our package, answers to most of them don’t matter, you can just press Enter.
The question “Set currently installed components as dependencies?” should be answered with “yes”—all previously installed components (in our case it’s jQuery) will be automatically placed in the created JSON file. The question “Would you like to mark this package as private which prevents it from being accidentally published to the registry?” should also be answered “yes”—this will prevent accidental publication of the package into the Bower registry.
Let’s install a few more packages:
bower install --save social-likes jquery-icheck fotorama
And take a look at what we got:
bower check-new Checking for new versions of the project dependencies..
│ └── jquery
│ └── jquery
bower list command shows a list of all installed packages. Here we see that all packages depend on jQuery, and that Bower found a version suitable for them all: 2.1.0.
In the file system it looks like this:
tree -L 2
5 directories, 1 file
Each package is installed into its own folder, there are no nested packages, and jQuery is only included once. In the project root lies the created by
bower init file
bower.json, but now it lists all the packages shown by
bower list, not just jQuery.
For uninstalling packages the
bower uninstall command is used:
bower uninstall --save jquery-icheck
You can confidently delete the
bower_components directory or add it to your
bower install (without additional parameters) command will return everything to the way it was:
Deploying the project
There are two approaches for deploying a project:
- Only the manifest file is added to the repository and all packages are installed during deployment. This way there is nothing unnecessary in the repository, but if GitHub crashes during deployment or another server from which packages are installed crashes, there will be problems.
bower_components folder as well as
bower.json are added to the repository. This way deployment doesn’t depend on external servers, but the repository blows up with hundreds (if not thousands) of extra files.
Semantic versions (semver)
Semver is, first-of-all, an approach to versioning libraries: a format for version numbers MAJOR.MINOR.PATCH and rules, which have to be followed when incrementing each number.
Secondly, it’s a method of describing necessary dependencies, which is used by Bower and npm.
While installing with the
--save flag, package version are added to
~1.0.1. The tilde at the beginning means that during installation version 1.0.1 will be chosen, or a version with a larger last number (PATCH) if it’s available. This way the installed version will have the latest bug fixes, but will be fully compatible with the one specified in the manifest file.
Bower has a
bower update command, but it updates packages with respect to the demands of the manifest file. For example, if it lists jQuery ~2.0.0 Bower can update jQuery to version 2.0.9, but 2.1.0 won’t be installed because it doesn’t satisfy the ~2.0.0 formula.
To update packages (and
bower.json) to the truly latest version you can use the bower-update utility. Installation:
npm install -g bower-update
Searching for packages
There are two methods for finding packages with Bower: geeky and normal.
bower search jquery
Normal: open bower.io/search in a browser.
Bower puts the problem of project builds on the shoulders of the developer. The simplest method is just to concatenate the JS files with Grunt, Gulp or any other task runner that you use.
I use Grunt, so I’ll describe how to concatenate the packages with Grunt. There was a big article on using Grunt in the June issue of last year, so I’ll show my config of the
grunt-contrib-concat plugin right away:
This method has many downsides: you have to watch the files for each package, make sure that the files are assembled in the right order (for example, jQuery has to be higher than scripts depending on it). The grunt-bower-concat plugin can do this for you: it automatically concatenates all installed dependencies in the right order into a single file:
Registering your packages
To make your library available to be installed with Bower it has to be registered. To do this:
- at the root of a project there should be a
bower.json manifest file.
- the project should be a git repository (for example on GitHub)
- the project should use semantic versioning and the repository should have a git tag for the latest version
To create the manifest file the
bower init command is used:
[?] name: awesomelib
[?] version: 0.0.1
[?] description: My awesome jQuery plugin.
[?] main file: jquery.awesomeplugin
[?] keywords: jquery awesome yay
[?] authors: Artem Sapegin <firstname.lastname@example.org>
[?] license: MIT
[?] homepage: https://github.com/sapegn/jquery.awesomeplugin.js
[?] 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? No
description: 'My awesome jQuery plugin.',
'Artem Sapegin <email@example.com>'
[?] Looks good? Yes
And, although it’s mandatory to fill in the
name field, other fields are also very useful:
keywords will help users find your library through the package search interface.
main determines the main file of the package. Thie field can be used by automatic build tools like
license—always specify a license: it tells a potential user of your package whether they can use it in their project. For example, the
GPL license required that every project using it is also released with the same license, which isn’t always possible.
ignore—by default Bower will download the whole repository, which, firstly, will increase installation time, and, secondly, will add unnecessary files to the project. It’s best to exclude everything except the files required for the package to work (main JS file, CSS, etc.), license and README.
dependencies—all packages on which your package depends.
Now we need to commit the
bower.json file, create a git tag with the latest version and push it to the remote repository:
git add bower.json
git commit -m "Add bower.json"
git tag "v0.0.1"
git push origin --tags
Now you can register your package:
bower register jquery-awesomeplugin git://github.com/sapegin/jquery-awesomeplugin.git
From now on, Bower will check package updates, you just have to create git tags for each new version.
To make updating your packages easier you can use tools like grunt-bump or mversion.