Full-Stack JavaScript With MEAN And Yeoman

December 12, 2013

2713158505_b854770190_b

Introduction

A trend proliferating amongst prototypers in the Angular community is full-stack JavaScript development via the MEAN stack.

The acronym stands for: (M)ongoDB - a noSQL document datastore which uses JSON-style documents to represent data, (E)xpress - a HTTP server framework on top of Node, (A)ngular - as you know, the JS framework offering declarative, two-way databinding for webapps and (N)ode - the platform built on V8’s runtime for easily building fast, scalable network applications.

Supporters of the stack claim the use of JavaScript all the way down increases productivity and it's hard to dispute that this notion is pretty appealing. You get consistent models across the stack and consistent best practices in many cases too.

For example, in the case of Mongo - you can store documents in a JSON-like format (BSON - Binary JSON objects), author JSON queries in Express/Node and pass these JSON documents back to an Angular powered frontend. At a high-level, this is compelling and certainly make ease debugging when the objects in your database are identical to those your JS sees.

Note: There is little about the MEAN stack heavily coupled to Angular and a developer could substitute it for Backbone.js, Ember.js, Polymer or any other framework without losing the single-language stack advantages it offers.

Why MongoDB?

As mentioned, the choices in this stack, such as Mongo, enable the use of one language the whole way through. A fair discussion about the merits and critiques of the noSQL movement could easily fill several pages. We used MongoDB at scale back in my days at AOL and in the past two years I've seen an equivalent number of success and failure stories.

Critics of the MEAN stack sometimes point out that MongoDB may work well here for small-mid sized apps, but less so for large-scale applications (e.g 100's of millions of users). I would say it entirely depends on what you're trying to do. SQL databases, being strongly typed in nature are great at enforcing a level of consistency, ensuring many kinds of bad data simply don't get recorded in the first place.

NoSQL however is weakly typed, making very few attempts at data validation so that responsibility is placed back on the developer. They're particularly well suited to storing data which is inconsistent (as a collary, this makes it great for prototyping when the data model rapidly changes).

The technical differences between SQL databases vs noSQL really come down to a tradeoff between performance and reliability. There may be cases where transactions against a data store simply won't be modified once set. Mongo may be a good fit here. In other cases, you may have more complex transactions involved many separate logical units. There isn't a simplistic data model in Mongo that gives you a level of atomicity and SQL may be a better fit here.

At the end of the day, you should figure out what your requirements are and choose the right tool for the right job - regardless of whether you opt for the M in MEAN or not.

Why Express?

Express is simply a utility belt for authoring webapps with Node. It offers simpler interfaces for creating request endpoints, cookie handling and so on than you would get out of the box with Node on its own. It also gives you functions for everything you may need to build your own web server. Some of the things Express does well are:

  • Enabling REST routes that are as simple as: app.get(/account/:id, function(req, res){ /* req.params('id') is available */ });
  • Easy templating through Jade or Mustache
  • Automated HTTP header handling: app.get('/', function(req,res){ res.json({object: 'foo'}); });
  • Support for Connect middleware for plugging in synchronous functions to handle different things with requests or responses, such as authentication
  • Utility functions for parsing the POST request body
  • XSS prevention tools
  • Graceful error handling

Without Express, you’re likely to end up authoring your own routing logic regardless but it also gives you access to plugins and a system that’s relatively extensible.

Boilerplate for MEAN stack

mean.iois a decent starting point for those looking for a boilerplate to get started with this stack. It aims to solve common integration problems, is well-maintained, documents the additional packages that can be added to the stack and has inspired Yeoman generators such as generator-meanby James Cryer.

Yeoman and the MEAN stack

So, assuming that (a) we agree Mongo is suitable for at least prototyping in full-stack JS development and (b) we acknowledge that Angular may be superseded at some point in the future by another JavaScript framework, any tools that can help us get this stack setup quickly and easily could be quite useful.

This is where the Yeoman workflow comes in. It's composed of three tools you've probably heard of:

  • Grunt is used to build, preview and test your project, thanks to help from tasks curated by the Yeoman team and grunt-contrib.

  • Bower is used for dependency management, so that you no longer have to manually download and manage your scripts, plugins or front-end packages.

  • Yo scaffolds out a new application, writing your Grunt configuration and pulling in relevant Grunt tasks and Bower dependencies that you might need for your build.

About a year ago, I and a number of others in the Yeoman community worked on a project called ExpressStack. The idea was simple - give you a set of tools for scaffolding out everything you need for full-stack JavaScript development. We've since deprecated ExpressStack but in it's place, a number of similar projects have sprung up which are compatible with newer versions of Yeoman.

Let's summarize them.

Note: You'll need to have Yeoman installed (npm install -g yo) and one of the following generators, which you can install with npm install -g <generator-name>.

generator-angular-fullstack

An AngularJS generator, integrated with support for Express with optional MongoDB integration.

Features:

  • Livereload of client and server files

  • Express server integrated with grunt tasks

  • Easy deployment workflow.

  • Supports Jade templates

Write-up: http://tylerhenkel.com/creating-apps-with-angular-and-node-using-yeoman/

generator-meanstack

Another MEAN stack generator, compatible with grunt-express. Some of the things this does:

  • Replace connect with express on generator-angular.

  • Livereload on both backend and frontend files.

  • Bootstrap the application using an app_grunt.js file which refers to app.js with route definitions.

  • Use the same folder structure generated by the generator-angular with few modifications.

also see https://github.com/Grievoushead/generator-express-angular, which hasn’t been updated in a few months but does include sub-generators for a number of common tasks associated with MEAN stack development.

generator-mean-seed

A Yeoman generator for MEAN-seed, giving you a stack with Mongo, Express, Angular, Yeoman, Karma and Protractor for automated testing

generator-klei

Similar to the other generators, this also uses Mongoose and Stylus. Other features:

  • A scalable directory structure (Todo list example included)

  • A fully configured Gruntfile with livereload, linting, concatenation, minification etc.

  • Automounting of API routes using exctrl

  • No more editing of your html layout when adding scripts and stylesheets to your project, thanks to grunt-injector

  • Frontend unit testing with Karma, Mocha and Chai

ultimate-seed-generator

A generator supporting the MEAN stack with a number of other batteries included, such as Passport and Browserify.

  • AngularUI, Barbeque, Bootstrap

  • Bower, Browserify, Express, Font Awesome

  • Grunt, Handlebars, jQuery, JSHint, Karma/Mocha

  • LESS/LESSHat, Livereload, Lodash/Underscore

  • Modernizr, MongoDB/Mongoose, Passport

What should I use?

The obvious question after looking through the list of generators above is: “What should I use?”. I’ve ordered the list based on several factors, including how well the generator works with newer versions of Yeoman and how actively maintained the projects have been.

There’s clearly plenty of interest from the community in automated tooling for the MEAN stack, but what we really need is to get behind one or two generators that we can rally behind to improve, stabilize and scale out.

My hope is that this post will increase awareness of some of the current efforts in the Yeoman community to get out a great MEAN generator so we can solve this.

Is full-stack JavaScript practical for large production-level apps?

JavaScript all the way through is fantastic (at least for prototypes), however be careful not to shoehorn yourself into using it just because it's claimed to be the holy grail. That said, we're seeing an increase in the number of large-scale apps being built with similar stacks by the likes of Walmart and LinkedIn so more examples of this are almost certainly on the horizon.

It’s also worth noting that building a backend in Node is considerably more challenging than with other languages, such as Ruby, Python or Java. You have to manage memory leaks, keep in mind CPU-bound computations off the event loop and be very careful with exception handling unless you want to crash your entire app server. Many of these problems have already been solved with other platforms. That doesn’t mean Node can’t be used in production. It clearly can, but just requires further care.

Practically speaking, it's going to be challenging for there to ever be a "one-size" fits all language or tool for developing for the web and some skepticism for the MEAN stack is to be expected.

There's a huge amount of variance in front-end and back-end design patterns, principles and styles of doing things. If you find that PHP or Rails are more sensible options for your stack, use them, otherwise MEAN remains an option at least worthy of exploring at this time.

Other resources

With thanks to Pascal Hartig and Sindre Sorhus for their review.