It is common to organize the code in several modules when we are developing
Javascript applications. In Node.js ecosystem, we can import a module with
the require()
function and export symbols by adding them to the
module.exports
object. On the other hand, ES2015 adds import
statements and export
keywords. But unfortunately, both of these
techniques are not supported by any browsers. To deploy our Javascript
applications through browsers, we have to bundle our Javascript source code with
Browserify in advance.
Bundling Modules into One File
We can install Browserify with:
$ npm install -g browserify
And then, we can bundle Javascript source files with:
$ browserify -o [output.js] [mainapp.js]
Example
In this example, we separated our code into three modules: utils.js
,
posts.js
, and app.js, and we would like to bundle them into one
output.js
.
This is the content of utils.js
:
function findMin(array, lessThan) {
return Array.prototype.reduce.call(array, function (a, b) {
return lessThan(a, b) ? a : b;
});
}
function findMax(array, lessThan) {
return Array.prototype.reduce.call(array, function (a, b) {
return lessThan(a, b) ? b : a;
});
};
exports.findMin = findMin;
exports.findMax = findMax;
This is the content of posts.js
:
function Post(title, numVisited) {
this.title = title;
this.numVisited = numVisited;
}
Post.prototype.toString = function () {
return this.title;
};
function compareByTitle(a, b) {
return (a.title < b.title);
}
function compareByNumVisited(a, b) {
return (a.numVisited < b.numVisited);
}
exports.Post = Post;
exports.compareByTitle = compareByTitle;
exports.compareByNumVisited = compareByNumVisited;
This is the content of app.js
:
var posts = require('./posts'),
Post = posts.Post,
compareByNumVisited = posts.compareByNumVisited,
compareByTitle = posts.compareByTitle;
var utils = require('./utils'),
findMin = utils.findMin,
findMax = utils.findMax;
var array = [
new Post('b', 3),
new Post('c', 1),
new Post('a', 2),
new Post('d', 5),
new Post('e', 4),
];
var leastPopular = findMin(array, compareByNumVisited);
var mostPopular = findMax(array, compareByNumVisited);
console.log('Least Popular:', leastPopular.toString());
console.log('Most Popular:', mostPopular.toString());
var minTitle = findMin(array, compareByTitle);
var maxTitle = findMax(array, compareByTitle);
console.log('First in Alphabetical Order:', minTitle.toString());
console.log('Last in Alphabetical Order:', maxTitle.toString());
Now, we can bundle Javascript source files with:
$ browserify -o output.js app.js
Then, we can run output.js
with:
$ node output.js
Least Popular: c
Most Popular: d
First in Alphabetical Order: a
Last in Alphabetical Order: e
We can also create index.html
to include output.js
and test
the bundled output in the browser:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>Test</title>
<script type="text/javascript" src="output.js"></script>
</head>
</html>
Source Map
Bundling several Javascript modules into one makes it more difficult to debug. A
developer has to spend time finding the corresponding module. Source Map
was created to map the processed Javascript file back to their source Javascript
files. To generate source map with browserify
, specify -d
option:
$ browserify -d -o output.js app.js
And then, open the debugger in your favorite browser (remember to enable source map support in your browser.)
For example, if you add undefined
to the end of array
, then you
will see the differece:
var array = [
new Post('b', 3),
new Post('c', 1),
new Post('a', 2),
new Post('d', 5),
new Post('e', 4),
undefined, // CHANGED
];
ECMAScript 2015
To bundle ECMAScript 2015 source files, we have to transform them with
babelify
(the Babel transpiler integration).
First, we have to install babelify
and babel-preset-es2015
:
$ npm install -g browserify babelify babel-preset-es2015
Second, pass extra -t
option when we are bundling source files:
$ browserify -o output.js -t [ babelify --presets [ es2015 ] ] app.js
For example, here is the content of utils.js
(using ES2015):
export function findMin(array, lessThan) {
return Array.prototype.reduce.call(array, function (a, b) {
return lessThan(a, b) ? a : b;
});
}
export function findMax(array, lessThan) {
return Array.prototype.reduce.call(array, function (a, b) {
return lessThan(a, b) ? b : a;
});
};
This is the content of posts.js
(using ES2015):
export function Post(title, numVisited) {
this.title = title;
this.numVisited = numVisited;
}
Post.prototype.toString = function () {
return this.title;
};
export function compareByTitle(a, b) {
return (a.title < b.title);
}
export function compareByNumVisited(a, b) {
return (a.numVisited < b.numVisited);
}
This is the content of app.js
(using ES2015):
import {Post, compareByNumVisited, compareByTitle} from './posts';
import {findMax, findMin} from './utils';
var array = [
new Post('b', 3),
new Post('c', 1),
new Post('a', 2),
new Post('d', 5),
new Post('e', 4),
];
var leastPopular = findMin(array, compareByNumVisited);
var mostPopular = findMax(array, compareByNumVisited);
console.log('Least Popular:', leastPopular.toString());
console.log('Most Popular:', mostPopular.toString());
var minTitle = findMin(array, compareByTitle);
var maxTitle = findMax(array, compareByTitle);
console.log('First in Alphabetical Order:', minTitle.toString());
console.log('Last in Alp`habetical Order:', maxTitle.toString());
Bundle source files with browserify
command and babelify
:
$ browserify -o output.js -t [ babelify --presets [ es2015 ] ] app.js
Finally, run the output script:
$ node output.js
Least Popular: c
Most Popular: d
First in Alphabetical Order: a
Last in Alphabetical Order: e
Epilogue
In this post, we introduced Browserify
which is able to bundle multiple
Javascript source files into one output file. We also mentioned the concept of
source map and ES2015 transformation. Hope you enjoy this article.