Create a gist now

Instantly share code, notes, and snippets.

Annotated Browserify Gruntfile
/**
* Annotated Gruntfile.
* This builds a Backbone/Marionette application using Dust.js (Linkedin fork) as a
* templating system, as well as some helpers from Foundation, with Browserify.
* It also configures a watcher and static server with live reload.
*/
module.exports = function (grunt) {
// This automatically loads grunt tasks from node_modules
require("load-grunt-tasks")(grunt);
// This installs timers so you can monitor how log each of your build steps take
require("time-grunt")(grunt);
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
// grunt-contrib-jshint
jshint: {
all: {
// Monitors all files except for vendor code
src: ["Gruntfile.js", "test/**/*.js", "app/**/*.js", "!app/vendor/**/*.js"]
},
options: {
// I strongly reccommend using a .jshintrc, that way your editor can use it too
jshintrc: "./.jshintrc"
}
},
// grunt-contrib-watch
watch: {
lint: {
files: ["Gruntfile.js", "test/**/*.js"],
// grunt-newer is also included. It will dynamically modify the jshint
// config so only files that changed will be linted
tasks: ["newer:jshint:all"]
},
dust: {
// automatically recompile dust templates
files: ["app/templates/**/*"],
tasks: ["dust"]
},
browserify_main: {
// only rebuild when our core when our app changes
files: ["app/**/*.js", "!app/vendor/**/*.js"],
tasks: ["browserify:main", "newer:jshint:all"]
},
browserify_vendor: {
// rebuild when our 3rd party code changes
files: ["app/vendor/**/*.js", "tmp/dustjs.compiled.js", "node_modules/*/package.json"],
tasks: ["browserify:vendor"]
},
concat: {
// automatically reconcatenate
files: ["tmp/*browserify.js"],
tasks: ["concat"]
},
livereload: {
// reload our testing page
files: ["public/**/*"],
options: {
livereload: true
}
}
},
// grunt-browserify
browserify: {
/**
* Vendor library build
*/
vendor: {
files: {
// build to a temp folder. The `main.js` just calls require("jquery").noConflict()
"tmp/vendor.browserify.js": ["app/vendor/main.js"]
},
options: {
// The shim config
shim: {
// Although jQuery is available on NPM, it is faster to shim it.
// It has no dependencies and exports window.$
jquery: {path: "app/vendor/jquery-2.1.0", exports: "$"},
// Shim Backbone
backbone: {
path: "app/vendor/backbone-1.1",
exports: "Backbone",
depends: {
// although Backbone depends on Underscore, we can easily substitue Lodash
lodash: "_",
jquery: "jQuery"
}
},
// Marionette is similar
marionette: {
path: "app/vendor/backbone.marionette",
exports: "Marionette",
depends: {
lodash: "_",
backbone: "Backbone"
}
},
// We also shim our templates, since they rely on a global "dust" variable
templates: {
path: "tmp/dustjs.compiled.js",
// the actually don't have an export -- they just augment the build in dust object
exports: null,
depends: {
dust: "dust"
}
},
// Some Foundation helpers, similar to jQuery plugins
// (The Sass part of Foundation is left out of this Gruntfile)
foundation: {
path: "app/vendor/foundation",
exports: "Foundation",
depends: {jquery: "jQuery"}
},
foundation_offcanvas: {
path: "app/vendor/foundation/foundation.offcanvas",
exports: null,
depends: {foundation: "Foundation"}
},
foundation_accordion: {
path: "app/vendor/foundation/foundation.accordion",
exports: null,
depends: {foundation: "Foundation"}
}
},
// Custom aliases
alias: [
// collapse all require()s of lodash into a single version
// If you need this to work on IE8, alias to the compatibility build instead:
// "node_modules/lodash/lib/lodash.compat.js:lodash"
"lodash:lodash",
// make the linkedin fork of dust available as require("dust")
"dustjs-linkedin:dust"
],
// Rather than use the default minified module loader, use the unminified
// source for easier debugging
prelude: grunt.file.read("./node_modules/grunt-browserify/node_modules/" +
"browserify/node_modules/browser-pack/prelude.js")
}
},
// The main browserify build
main: {
files: {
// Build from the main entry point into a temp folder
"tmp/main.browserify.js": ["app/main.js"]
},
options: {
// All of these modules come from the vendor build, so we have to tell
// browserify to not include them
external: [
"lodash",
"jquery",
"backbone",
"marionette",
"dust",
"foundation"
],
// again, use the unminified dev prelude for easier debugging
prelude: grunt.file.read("./node_modules/grunt-browserify/node_modules" +
"/browserify/node_modules/browser-pack/prelude.js")
}
}
},
// Custom dust task. This compiles dust templates into functions
dust: {
options: {dustVarName: "dust"},
render: {
files: {"tmp/dustjs.compiled.js": ["app/templates/*.html"] },
options: {base: "app/templates/"}
}
},
// grunt-contrib-concat
concat: {
all: {
// stitch the two browserify bundles together.
src: ["tmp/vendor.browserify.js", "tmp/main.browserify.js"],
dest: "public/js/main.js",
options: {
// It includes semicolon.js!
// This is needed to prevent the two concatenated IIFE's fro each bundle being
// interpreted as a function call
separator: ";\n"
}
}
},
// grunt-contrib-connect
// A really simple static web server that supports live-reload
connect: {
dev: {
options: {
port: 8888,
// public/ contains an index.html that just includes js/main.js
// (as well as CSS and the basic page layout)
base: "public",
livereload: true
}
}
}
});
// Default task. Build, start the server, and watch files for changes
grunt.registerTask("default", ["build", "connect", "watch"]);
// Build task. Compile templates, browserify, and concat
grunt.registerTask("build", ["dust:render", "browserify", "concat"]);
};
@ragulka
ragulka commented May 11, 2014

Interesting. I'm curious how you would write tests for your modules and run them in node instead of browser. Mostly, I am wondering if and how it would be possible to simulate the shims and aliases for node?

@blacksonic

What is in app/vendor/main.js? It requires every dependency and then call jQuery.noConflict?

@blacksonic

Can you make it into an example repository?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment