Skip to content
This repository has been archived by the owner on Feb 8, 2019. It is now read-only.

Browserify

Chad Watson edited this page Jul 16, 2015 · 18 revisions

Contents

Folder Structure

├───config/              # Configuration files
├───lib/                 # Typically tools and such. Polyfills, plugins.
├───modules/             # Reusable modules. Probably export some methods and properties
├───templates/           # EJS templates
└───views/               # Page-specific code

Introduction

Browserify takes a set of js files and concatenates them into a single bundle file to be used on all of your pages. It doesn't do anything fancy when the page loads. It does its work while you're developing. The idea is to have a single HTTP request for your scripts instead of multiple requests for script files which block the rendering of your page. You also take advantage of browser caching since you are always serving the same file.

For a better overview check out this article For a more in-depth understanding of Browserify, [check out the Browserify handbook(https://github.com/substack/browserify-handbook).

Bundles

To create bundles add items to the array in _src/js/config/bundles.js.

// This file should be `require`d in `gulpfile.js`
// and set on options.browserify.bundles
// so that the gulp task knows which bundles to make

// Main bundle config
var main = {
  outputName: 'main.js',
  entries: [
    './modules/responsiveImages',
    './modules/sampleModule'
  ]
};
// Blog bundle config
var blog = {
  outputName: 'blog.js',
  entries: [
    './modules/responsiveImages',
    './views/blog'
  ]
};
// Expose an array including the bundles
module.exports = [main, blog];

outputName – The name of the bundle to be created.

entries – The modules to be included in the bundle. Must be included manually.

Don't get hung up on the order of the entries in the array. Browserify takes care of that through its knowledge of the CommonJS module system.

Notice that ./ in the file paths in the entries array denotes a relative path to _src/js/. Also notice that the .js extension is optional.

Entries

So what modules should you include in the entries array? Interesting question.

Browserify does some magic to include modules that are required from other modules even if they aren't included in the entries array. However it's not a mind reader. It needs to know where to start. So typically the modules you will include in the entries array are the ones that don't export anything. They are kind of the end of the dependency chain.

For example. Consider the four imaginary files in the following section. Only d.js would need to be included in entries. While all four modules will need to be included in the bundle Browserify is smart enough to take care of pulling in a.js, b.js, and c.js through the dependency chain when running gulp browserify.

In this case bundles.js would look something like this:

var main = {
  outputName: 'main.js',
  entries: ['./d.js']
};

module.exports = [main];

Quick CommonJS Overview

Browserify modules are written using the CommonJS module format module.exports = .... Whenever you reference a module inside of another module with require('./module') you get a reference to whatever that module exports.

For example:

a.js

module.exports = {
  property1: 'Hello',
  property2: '!'
};

This file exports an object with two properties.

b.js

var a = require('./a');

module.exports = function(input) {
  return a.property1 + ' ' + input + a.property2;
};

This module references a.js and has access to the two properties it exported. It exports a function that can take a parameter input when being called from another module.

c.js

var b = require('./b');

module.exports = function() {
  var sayHello = b('George');

  console.log(sayHello);
};

This module exports a function that calls the function exported by b, passing it a string, and then logs the result to the console. But of course c's function doesn't do anything until it is called from another module.

d.js

var c = require('./c');

c();
// "Hello George!"

Finally, d uses c which requires b which requires a.

Note that a.js could be rewritten like this:

module.exports.property1 = 'Hello';
module.exports.property2 = '!';

or simply:

exports.property1 = 'Hello';
exports.property2 = '!';

Relative Dependencies

Whenever you use require you reference your own modules by prepending the filename with ./path/to/. This tells Browserify to look for a module relative to the current one. If you only use the filename Browserify will think that you are trying to reference a module inside the node_modules directory which was installed with npm.

tl;dr

Reference a file in the same directory:

var module = require('./module');

Reference a file in a child directory:

var module = require('./myfolder/module');

Reference a file in a sibling directory:

var module = require('../module');

Reference a module installed with npm install module:

var module = require('module');

waitFor Helper

_src/js/lib/waitFor.js

waitFor is a simple helper module you can use to keep a module's functionality from running until a selector is in the DOM. After running the init task you will also notice that this file has been aliased inside of package.json so that you can simply use require('waitFor') inside of your modules. That way you don't have to mess with all the relative paths.

Examples:

var waitFor = require('waitFor');

function hello() {
  console.log('Hello!');
}

waitFor('header.some-class', hello);

or multiple selectors

waitFor('header.some-class, .another-class', hello);

Transforms

Browserify can utilize transform modules, like Babel or CoffeeScript, to transform your module's code. Declare your transforms in the configuration object that you pass into your instance of gulp-eta and Browserify will handle that.

options.browserify.transform = []; // your transforms

Here's a good list of Browserify Transforms

Eta makes use of the EJS and Browserify Shim transforms.