The MECH Stack — Solving JavaScript Framework Fatigue

This article introduces the results of my year-long quest for the ideal server/client JavaScript stack. I’ve spent months exploring available options, finding some products, libraries and services that I really like, almost reaching the conclusion that each was the best choice for my projects, only to find a fairly big “gotcha” each time.

Edit/Update: It seems that some folks are reading more into this article than I intended. The key words above are “the best choice for my projects”. That said, the purpose of my writing this is to share that experience with web developers in case others find it useful or at least slightly informative. I’m not “proposing” anything. I’m not “introducing” anything. I’m documenting where my journey led, after I had already eliminated Angular, React, and some of the other popular web platforms and libraries. I have nothing against them; I will probably eventually use them all, but not for my projects in the near-future. Settling on a small number of core platforms and libraries has eased my JavaScript Framework Fatigue. It may add to yours, if you have not yet heard much about Hapi.js or Ember.js.

I’ve been experiencing JavaScript Framework Fatigue on an almost daily basis, and told myself repeatedly “just pick something”, only to see something the next day that might be revealing how tragic my earlier choice would have been. It’s a never-ending process, that fortunately, for me, seems to finally be settling down. A couple of key JavaScript technologies have been holding as the best choice, for some time now. Actually it’s been a few months and my mind (and my book budget) are finally getting a well-deserved break from new things.

Beyond being written in JavaScript, my requirements were fairly easy, mostly just that if it was a full-stack end-to-end implementation (like Meteor or Sails.js), that it be a rich environment that just worked with direct support or add-ons for a variety of services such as back-end storage and authentication that I’d eventually need. If it included its own view support, it would need to be easy-to-read and maintainable. Ideally it would be capable of providing individual independent components, and if it did not satisfy my end-to-end needs, it needed to be the opposite: solving a specific portion of those needs while not imposing use of certain other frameworks and libraries (or at least not too many). A JavaScript library with narrower focus would need to solve a specific responsibility well, without ruling out the use of different libraries or tools for other tasks for other pieces of the equation. And there needed to be a solution for all of this that enabled mobile development as well as website app.

What did I look at? Well I started with MEANNode.js to enable a server-side solution written in JavaScript; and of course learned Angular, Express, Sane, Koa, Meteor, Sail.js, services like Firebase, Parse, Syncano, Appgyver, Appery, Monaca, Serverless and others, Apache Cordova, Ionic, Vue.js and numerous other frameworks.

In this article, I’m not going to get into the “Bootstrap vs Material Design vs. others” discussion, other than to say that I find Google’s Material Design elements to be far less intuitive than alternatives: mostly attractive graphic design, but at the expense of intuitive functionality. I won’t be using it.

But let’s cut to my conclusions here:

MECH = MongoDB + Ember.js + Cordova + Hapi.js

Obviously any server-side JavaScript solution is probably also based on Node.js. The core frameworks I’ve decided on are are: Hapi.js on Node.js plus storage (currently Mongo because of wide support, easy of deployment and reasonable storage and pricing).

Then on the client side, Ember.js provides a full-featured app experience with the rapid and flexible user interfaces that I expect, with the addition of Cordova or Electron depending on the non-browser target platform. The Cordova part solves the cross-platform mobile app portion, and similarly I could add Electron for turning it into a desktop app.

So to me, the JavaScript technologies that really shine here are:

Node.js + Hapi.js + Ember.js

Unfortunately that doesn’t make for a very useful acronym.

Hapi.js + Ember.js = a lean, mean app machine

Let’s look at these more closely.

Hapi.js

hapi.js

Among the many server-side and full-stack frameworks, Hapi.js stood out. First, it was small and fast, but more than that, it is really really easy and intuitive to use. It feels like a smaller project even though it is a very rich and fairly complete server-side framework. But it has been a critical part of the deployment to many of the world’s largest sites, including its primary developer, Walmart Labs, and many others. It’s extremely simple to use, and just handles many of the mundane things that computers should handle, such as setting the MIME type on HTTP requests according to the type of data returned in the reply. It’s capable of handling all of Walmart’s mobile app requests on Black Friday; so I’m reasonably confident it won’t be the weak link in my app.

And it’s easy to use. The following JavaScript code is the full source for a Node.js REST application which listens on a GET handler for a ‘/’ route and echos the HTTP headers supplied on the call back to the caller as a JSON response. (Yeah, it’s almost entirely automatic.) Does coding up a whole server get any easier than this?

Ember.js

As someone who has been a professional software developer since January 1984, I clearly remember the initial excitement I had the first time I started understanding what I was reading about Angular.js. Oh how far the world of JavaScript development had come in such a few short years. One of my colleagues was also very keen on React.js, so I also needed to investigate the state of things there. What I found in both cases were fine projects, yet there were a few things that nagged me about Angular, and I wondered if it couldn’t just be done better. And a few things about React that really made me feel like it might be a step backwards.

One of the biggest lessons of my three decades as a professional software developer was the importance of maintainability, and readability. The code needed to be very readable, and easy and most importantly obvious. Put bluntly, obvious code has very little chance of being buggy. But if there is a problem, it’s typically a lot simpler to identify and fix.

An Angular project was simply not as readable and maintainable as Ember code. And React went well beyond that and failed my “obvious test” in significant ways. Ember “just works”.

Ember.js gives me a very readable user interface (view), detached from the data being represented (model), and the core logic that determines how that data will be used (controller). While Ember is famous for its extremely easy-to-use two-way binding, recent versions of Ember also provide the reactive programming model of one-way binding pushing down and events and actions bubbling back up. In fact, Ember components (rather than controllers) are now the recommended approach. It is a complete client package with a CLI with built-in generators for views, routes, components, etc.

I think the thing I like most about Ember is that it makes it easy to look at both logic code and presentation templates and understand almost immediately exactly what is going on, and what the structure of the app would look like when rendered.

Here’s an example from the Ember home page, which does something fairly complex. This code below displays the three most recent pull requests from the Ember.js project on GitHub. The controller in this case is automatic (implied), so all that is needed is first the model, then the actual HTMLBars template for the view:

app.js defining model
application.hbs — HTMLBars template for view

That’s not a lot of code for an application that displays the most recent three pull requests from a live GitHub project. Here is the output at the time of this article:

I think that’s pretty impressive for such a small amount of code. Yes there’s some CSS too (not included). See the Ember.js site for this and other examples.


I’m not going to make this article longer by writing too much about MongoDB or Apache Cordova. There are far too many articles and books that are much more appropriate out there, and the topics have been covered extensively. What I will say however is that Mongo’s use is so wide that it is a de facto storage mechanism now and the default in many cases, and it makes for an obvious choice if sticking with the majority appeals.

I’m a bit concerned by the reports a couple of years ago regarding its ability to fetch stale data on reads; some movement on that but it does not yet look resolved. However, that seems to only be an issue in cases in a fairly complex case where there is a cluster of Mongo servers and a master fails, in a particular combination of events, something we’ll all say “It will never affect my use case” and then be proven wrong when the application is a big hit and scaling up into the world of high-availability. For most of us, we’ll never get there and if we do, we can afford to assign someone to that problem then.

Honorable Mentions

Honorable mention to gun.js for data storage. I really like the design and approach but it just seemed too new and evolving to be used for a serious production project (yet). It’s incomplete in terms of background replication, but the design looks good and I think it’s a matter of time before it starts making serious waves. It’s something I’m going to be keeping a close eye on though. I think that’s a project that some corporate interests should come along and fund as full-time work with a full-time QA/doc/support team. Perhaps someone like Joyent, Mozilla or the Apache Software Foundation.

Although almost the complete opposite, I also really like the Firebase product. But have serious concerns about them following the Parse path with a mega-corporation buying them (in this case Google rather than Facebook) and then having other corporate needs that force changes. This has already been realized in the example of Firebase doing away with Firebase accounts, instead forcing login via Google accounts. (Not for the actually end-users of Firebase, just for the developers with accounts on Firebase. Er, not on Firebase. Anymore.)

Hapi.js + Ember.js = a lean, mean app machine