Better JavaScript Dependency Management with Browserify

Writing bundled JavaScript code for the browser tends to become a mess rather soon. We spend a lot of time arranging the code that has to be concatenated in the right order so every dependency gets loaded correctly.

Browserify can require dependencies for JavaScript like modules in node.js. This brings a lot of advantages to the way we can handle our required libraries.

better-javascript-dependency-management-with-browserify

What is wrong with plain JavaScript concatenation?

Most of the time when concatenating JavaScript files we’d list them all before running a concatenation task, making sure all the files are loaded in the correct order. We’d have to write out every single dependency by hand, especially when it comes to external libraries.

In a Gruntfile I’d first define a few paths to dependencies I got through Bower, npm or downloaded manually. Then I’d have to point to each file and make sure the order is correct.

src: [
	//libraries
    'bower_components/eventie/eventie.js',
    'bower_components/eventEmitter/EventEmitter.js',
    'bower_components/imagesloaded/imagesloaded.js',
	/* I DON'T LIKE DOING THIS! */

	//other files
    'src/!(base).js',

    //the base has to be last
    'src/base.js'
]

This might not look like such a big problem, but can be a pretty tedious task when you have to get new dependencies or when a dependency updates. The paths tend to leave a mess since most repositories have a different way of pointing to the main JavaScript files to include.

Another downside is that the files you want to include in your concatenation have to be "compiled" and include all the project's code and its dependencies.

Requiring JavaScript modules in browsers with Browserify

Node.js uses CommonJS to include modules in your code. We can install packages using npm and require them in our projects as modules. We can put these modules in an object to use and we don't have to worry about loading the correct files.

We can define which module the current file depends on so we can let CommonJS solve the rest. This, however, doesn't work in the browser. Browsers can't require files like node.js does.

This is where Browserify comes in and creates a wrapper around our required npm modules so we can use require() in the browser versions of our JavaScript.

var _ = require('underscore'); // > node_modules/underscore/underscore.js
var picturefill = require('picturefill'); // > node_modules/picturefill/picturefill.js

/* We can now use both objects as modules */

Browserify will bundle all the needed files into one and creates one output file.

Better coding through dependency management

Using Browserify also means we can use npm modules in our browser. If we, for instance, would want to use the package uniq: all we need to do is to install the package into our project executing the following line in your terminal:

npm install uniq

and place the following code in your JavaScript:

var uniq = require('uniq');

You can now use uniq as an object in your script.

Using Browserify from command line

You can choose to run Browserify from your terminal, but you can also choose to run Browserify as a task in your favourite task runner.

To use from CLI, install Browserify using npm:

npm install -g browserify

and bundle your package using:

browserify ./path/to/your/source.js -o ./destination/file.js

Using Browserify in Grunt

Install the grunt-browserify package.

npm install grunt-browserify

and setup the correct source and destination in the grunt config:

browserify: {
  dist: {
    files: {
      'destination/file.js':  ['path/to/your/source.js'],
    }
}

It gets even better using Browserify in Gulp

If you prefer to use Browserify in Gulp you can use the original package instead of a plugin. It's even not advised to use the Gulp plugin for Browserify.

Add Browserify as a dependency to your project:

npm install browserify --save-dev

Require Browserify in your gulpfile.js and use the following code to add a gulp task:

var gulp = require('gulp'),
    browserify = require('browserify');

gulp.task('browserify', function() {
    return browserify('./path/to/your/source.js') //read the main javascript file
        .bundle()
        .on('error', function (err) {
            console.log(err.toString());
            this.emit('end');
        })
        .pipe(source('output-name.js')) //name the file
        .pipe(gulp.dest('./output/folder/')); //output directory
});

I added the .on('error') callback so that Browserify won't break the loop when you're using the task inside of a watcher.

Creating your own (local) modules

Let's say we have a file called main.js. You can now include other files or packages with var package = require('name-of-module'), but we can also include our own modules pointing to the file.

If we'd have a module in a file called sum.js in the same folder as main.js we can require that module using var sum = require('./sum.js');. Note the ./ at the start of the path which is necessary for require() to know it's a file and not a package which resides in node_packages.

We can make our object or function available as a module by using module.exports in our code. Here is an example of what sum.js would look like:

function Sum(a, b) {
	this.a = a;
	this.b = b;
}

Sum.prototype.calculate = function () {
	return this.a + this.b;
};

module.exports = Sum;

We can now use it in main.js like so:

var Sum = require('./sum.js');

var calculation = new Sum(400, 20).calculate();

This makes creating your own npm packages a lot easier and makes them available for Browserify use instantly.

It makes our code way more manageable and makes the writing of it a lot more structured.

A lot of libraries are also available through npm

Since the use of Browserify over Require.js or other methods is gaining a lot of ground, a lot of JavaScript libraries are also becoming available on npm. This is great news if you want to use Browserify, since it will improve our dependency management dramatically.

I am currently rewriting a few of my libraries to be available as modules through npm. Consider doing this too.

Wrapping up

With Ecmascript 6 around the corner and front-end development moving forward very fast, this way of dependency management is finally something to hold on to.

If you want to share your experience about creating npm packages and using Browserify for your module requiring in browsers, feel free to comment below.

Static Mockup Data for your Endpoints with Connect

While working on a frontend project you’ll easily come to a point where you need data from a webserver that will be retrieved through an Ajax call. Serving mockup data from those endpoints is a tricky thing when you don’t run your frontend project on a webserver.

Luckily there is a way to easily write middleware using Connect for NodeJS. Other great thing: works with task-runners!

Static Mockup Data for your Endpoints with Connect
read more

Compound Selectors for Better Class Names in Sass

There are a few class naming conventions you can live by, the problem with most of them is writing long class names that tend to give your CSS a messy look without compound selectors.

Luckily Sass now supports compound selectors which will make our stylesheets a lot easier and better to maintain.

Better Class Names with Sass Compound Selectors

read more

Automating your JavaScript workflow using Grunt

Using tools like Grunt to improve your JavaScript development has been popular for quite a while. It’s not a surprise since it will truly improve your workflow and takes care of pesky tasks we so hate to do.

This article will go into detail about the way I like to use Grunt to improve my workflow and make it way easier to maintain and test my JavaScript projects.

Automating your JavaScript workflow using Grunt read more

Curse of the Open Source libraries and frameworks

The web development population has grown significantly over the past years. A lot of people are choosing development as their trade and make a good living out of it.

The number of people using frameworks or libraries to speed up their development, or solve the parts of development they can’t do themselves has increased as well.

Is it a good thing, or are we shooting ourselves in the foot? I will share my view on the matter in this article.

Curse of the Open Source libraries and frameworks

read more

Using WordPress plugins as Symbolic Links

If you want to use a single plugin on different WordPress installs you might want to go for a symlinked plugin folder. That way we can have one codebase and apply it on multiple installs.

That would be great right? Sadly, WordPress doesn’t support this (yet). In this post I’ll explain how I got WordPress to accept my plugins as symbolic links.

Using WordPress plugins as Symbolic Links
read more

Looking back at WordCamp Europe 2013

Last weekend I went to WordCamp Europe in Leiden. It was my first WordCamp and I have to say; it was very awesome. Can’t believe I’ve never been to an event like this before and I should really start doing it more in the future.

I’ll fill you in on the experience, the speakers and give you my two cents of what I thought about the talks.

Looking back at WordCamp Europe 2013 read more