Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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 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?

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

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