Using Bower for JS package management instead of NPM

This is a follow up to my post: Learning Gulp with Visual Studio – the JavaScript Task Runner

In my last post, i did the following:

  • Created a web project
  • Installed Node.js
  • Installed Gulp for running JS build tasks
  • Installed more JS libraries using NPM (node package manager)
  • Created simple HTML+JS app w/jquery
  • Created gulp tasks to minify and bundle JS into main.js
  • run proof of concept
  • added gulp task to post-build event so it is run automatically

In this post, i will make some changes to the above, in that i will replace the JS package manager NPM with Bower.

Why? NPM works, but has some disadvantages vs. Bower. NPM packages all keep copies of their own dependencies. This can result in multiple versions of libraries, like JQuery, even different versions. Bower uses a ‘flat’ model, so only one version is installed at a time.

Well, what about just using NuGet? That is possible too, but NuGet is not good at updating dependent versions after initial installation. If you install different NuGet packages with the same dependency, the “last one wins”.

To be completly frank, i think it’s kind of crazy to have 2 different JS package managers in the same project. But Bower does solve the problem of having a single “flat” package dependencies. I found some hacks/workarounds to do it in NPM, but i just can’t see making the brain investment unless i do node all day every day.

Installing Bower

Open the Node Command Prompt.

We are going to install it using NPM, globally:

npm install -g bower

At that point, we can install libraries using bower, similar to how NPM works.

You also need to install msysgit , but we already installed it when installing Git Extensions.

Bower uses Git to install packages.

Configuring  / .bowerrc

Packages will install to the bower_components/ directory. If you want to change the defaults, create a .bowerrc directory and set it.

If you want to change that, create a file in your project named .bowerrc and enter the JSON to specify:

{
    "directory": "js/lib"
}

The packages will get installed there instead.

I found trouble creating the file with a leading dot in Windows Explorer or Visual Studio. However, using Notepad, you can save a file with a leading dot.

Installing Gulp to the project, as a development tool

First we create a package.json file for our project.

npm init

We are going to use the Gulp task build tool, but that is not a client-side library. It is used as a development build-time tool, so we are installing it using npm.

npm install gulp --save-dev

We also need to install the gulp-* plugins we need at build time:

npm install gulp-uglify --save-dev
npm install gulp-concat --save-dev

Those commands create entries in your package.json file, under the key devDependencies. That means they can be automatically installed when the project is built on another machine.

Installing client-side packages

The whole point of Bower is to use it for client-side packages like JQuery, Angular, etc.

First, in the node command prompt, we will initialize it by creating a bower.json file. You can do it manually, or do the init command, and fill out the questions.

Here is what i got:

{
  "name": "GulpBowerWebTest",
  "version": "0.0.1",
  "authors": [
    "raulg <raulg@xxxxx.yyy>"
  ],
  "description": "Test using Bower",
  "license": "Proprietary",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "js/lib",
    "test",
    "tests"
  ]
}

Now i’m going to install some libs, like jquery (specific version 1.9.x).

bower-install-jquery-commandprompt-2014-10-30

Note in Solution Explorer (w/”Show all Files” on) they installed to /js/lib/, as specified in our .bowerrc

bower-install-jquery-sol-expl-2014-10-30

Updating Gulpfile.js

I copied the static index.html and app.js files from my prior project. I’m using the same Gulpfile.js, with only some updates to the paths, since they are in different locations:

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');

gulp.task('default', ['scripts'], function() {

});

gulp.task('scripts', function() {
    return gulp.src(['js/lib/jquery/jquery.js', 'scripts/**/*.js'])
      .pipe(concat('main.js'))
      .pipe(uglify())
      .pipe(gulp.dest('js/dist/'));
});

I’m trying out using Task Runner Explorer to run gulp. After tweaking and testing, i’m going to try checking the After Build event. This could be an alternative to setting it in the project’s post-build event. I’m not sure if its better yet, since i’ll need to have it work when building on the TeamCity CI server using MSBuild. Some VS tooling are not supported in MSBuild.

bower-taskrunner-afterbuildevent-2014-10-30

Now when i run the app, it works the same. The differences are that jQuery is at 1.9 version, and it should be easier to manage the client-side JS libs we use, and keep versions up to date and consistent (using the bower update command). I think that means jquery 1.9.x gets the latest, but will not go to 2.x if specified in the bower.json file.

References:

 

Leave a Reply

Your email address will not be published. Required fields are marked *