You don't have to use ampersand with browserify (or some other commonjs loader) but that's how we build everything, and we love it.
This is a quick run down of npm and browserify if you haven't used them before.
The below assumes you have installed npm and node.js on your system already.
Another great source of information about all this is the browserify handbook, written by the guy who wrote browserify.
npm (along with its command line tool, the npm-client) is the official package manager for node.js, but it works great for client-side JavaScript too. It helps you publish, consume, and manage modules of JavaScript code in your applications.
commonjs modules are a specification and implementation of a module system in JavaScript. They allow you to separate functionality into separate files or npm modules, that can then require each other. This makes it much easier to break the functionality of your application up into smaller chunks, that can depend on each other, rather than writing your code in one giant file.
browserify helps you write your application using commonjs modules, bundle it up into a single JavaScript file, and use in your application in the browser.
Put together, the flow of creating a very simple web application with these tools might look something like this:
mkdir my-project && cd my-project
- create a project directorynpm init
- create a package.json for your project which stores your dependencies and their versionsnpm install browserify --save-dev
- install browserify as a development only dependencynpm install underscore --save
- install a dependency you want to use in your applicationcreate a module in your application, say square-numbers.js
// ./my-project/square-numbers.js
// Squares a list of numbers
// Require the underscore npm module
var _ = require('underscore');
function squareNumbers (list) {
return _.map(list, function (n) { return n*n; });
}
//export squareNumbers as the module function
module.exports = squareNumbers;
create the main app.js file for your application, which requires your module
// ./my-project/app.js
console.log('Welcome to my application')
// require the local module
var squareNumbers = require('./square-numbers');
var input = [1,2,3,4];
console.log('Input is:', input);
console.log('Squared is:', squareNumbers(input));
./node_modules/.bin/browserify app.js -o app.bundle.js
- use browserify to compile your application down into a single file.
create a very simple index.html that loads your bundle:
<!-- index.html -->
<script src='app.bundle.js'></script>
open index.html
- open index.html in a browser, and check the console output.
The following sections go into more detail about the components, and tools you might use. If you have experience with node.js and writing commonjs modules, you can skip straight to browserify.
npm is the official package manager for node.js.
The various components of npm are:
npm
. This helps you npm install
dependencies from the registry, npm publish
dependencies, and so on.require()
them.If you are starting a project from scratch, create a directory for it on your system somewhere, and run npm init
from inside it, and follow the instructions (don't worry too much about the answers if you aren't sure yet).
mkdir my-new-project
cd my-new-project
npm init
Once you've done that you'll see a package.json file in your directory:
{
"name": "my-awesome-project",
"version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
This JSON file simply describes your project, and is where you can list any npm dependencies, and their versions, for your project. You'll also need this file if you want to publish your project to npm itself.
Installing dependencies with npm is really easy. To install ampersand-state run:
npm install ampersand-state --save
This will do a few things:
node_modules
directory in your project (if one isn't there) and install ampersand-state
into it, along with it's dependencies.Add a dependencies
section to your package.json, and add ampersand-state to it:
"dependencies": {
"ampersand-state": "^4.2.7"
}
npm install <module-name>
takes a number of options, two are --save
and --save-dev
. Both automatically add the module name and version to your project's package.json, either in "dependencies"
or "devDependencies"
. Use --save
for application dependencies, i.e. anything you require()
in your application/module. Use --save-dev
for anything you use to develop your application, e.g. browserify, or tests, etc.
All npm modules that you install will use the commonjs module specification. You can (and should!) use commonjs modules to break up your application code even if you don't publish them to npm individually.
A commonjs module is simply a file with some JavaScript in it. It might look something like this:
//A simple function as a module
var something = require('some-dependency');
function doSomethingSweet (input) {
return something(input);
}
module.exports = doSomethingSweet;
//A module which exports a constructor
var AmpersandModel = require('ampersand-model');
var MyClass = AmpersandModel.extend({
//...
});
module.exports = MyClass;
or like this:
//A hypothetical underscore like module
module.exports.map = function (list, fn) { ... }
module.exports.filter = function (list, fn) { ... }
module.exports.each = function (list, fn) { ... }
//...
A few things to note about the examples:
(function () { /*my code here*/ })()
module.exports
allows it to be accessible by any other module that require()
's your module. By default module.exports
is an empty object. You can either set properties on it to properties/functions, like the last example above; or replace it with a function/constructor like the first two.Requiring modules is easy. From a file, just use require, like so:
//require a module from npm, by specifying its module name
var _ = require('underscore');
_.each([1,2,3], function () { /*...*/ });
//require a local file, by relative file path, (you can omit the .js)
var MyView = require('./views/my-view');
var view = new MyView( /*...*/ );
//You can even require JSON files
var package = require('./package.json');
console.log(package.version);
Everything that was module.export
ed will be available as the result of the require()
statement in the parent file.
Npm and commonjs modules are how almost all backend node.js developers write and manage JavaScript code. Unfortunately for browsers we can't just point our index.html at the main app.js
file, as browser's don't understand how require()
works. And even if they did, if it had to grab a file over the network every time it got to a require
statement, your application would take forever to load.
Browserify is a tool that takes an application written with commonjs and npm modules, and bundles it up into a single file, that you can then use in a browser.
It also provides shims for most of the core node.js functionality, so that in theory you can use any npm module in the browser, even if it was initially written for backend code. However, in general, we use it more for its ability to make possible using commonjs modules in the browser, and we generally will use modules written specifically for the browser.
Browserify itself is an npm module, which installs a command-line script (browserify
), so using it is something like this:
npm install -g browserify #installs browserify as a globally available command line script
browserify path/to/app.js -o path/to/app.bundle.js
You point browserify at your "main" JavaScript file, the one which require()
's everything else your app needs, and browserify bundles it all into a single app.bundle.js
file that is entirely self contained with all the dependencies you need in it. You can then use that like a normal JavaScript file in the browser like: <script src='path/to/app.bundle.js'></script>
.
There are a number of different way to run browserify, depending on your setup.
The simplest, as explained above is just to install browserify, and run something like: browserify path/to/main/app/file.js -o path/to/output/bundle.js
.
If you're doing it this way, you may find watchify useful, which watches your source files, and automatically rebuilds you browserify bundle when necessary.
If you use grunt or gulp, there are plenty of plugins and recipes for each to run browserify as part of your build. e.g: grunt-browserify and Browserify+Uglify gulp recipe
beefy is a great little tool for developing small apps or modules. It's basically a simple static web-server that will browserify your source on the fly. From the docs, beefy:
node_modules
.We wrote (and love) moonboots. It's kind of like a production-grade version of beefy. You can use it standalone, or as part of your express or hapi server, and it will handle compiling and serving your JS and CSS code, including things like autoreload in development, and caching and minifying in production.
It is installed as a part of the example ampersand app so you can check it out there.
There is a lot more to npm and browserify than we covered here. Again, the browserify handbook is a great reference to take a look at.