The Agony of Choosing a Modern Web Stack

I thought I would write down my recent experience in choosing a web stack for a project I’m working on, and try to justify, at least to myself, the reasons for my choices.

In my mind, I was building a normal, regular kind of web application, with no particular requirements. Of course, this is delusional thinking, because every project has requirements, even if they are vague. The delusion works the other way too, as every application framework (at least on its home page) promises the moon. It requires some detective work to figure out why I wouldn’t want to use a particular framework for a particular project. Reading between the lines has never been my forté.

So this is the agony: Vague requirements + A plethora of choice + A tendency towards analysis-paralysis + The need for in-depth research + A desire for finding an optimal solution = AGONY.

The fact that analysis-paralysis and the current state of the javascript ecosystem have recently combined to make the perfect storm is nothing new, and many have already ranted about it. I’m late to the party, but no matter. Perhaps by reading about my experience you will be saved from the same fate, or at least be better prepared to meet it. Still, there’s nothing like experiencing something first hand to really understand a subject.

I’m now on my third web stack for my so-called “normal” web application! (If I include early prototypes, it would actually be the fifth.)


Web Stack the First

(circa September 2015)

Rationale

Ionic is primarily a front-end framework although the Ionic folks are working hard to make it a full stack solution.

I chose Ionic so that I could conveniently sidestep having to make a hundred other choices, since Ionic makes them for me. A liberating feeling, and no doubt the driving force behind the creation of web framework after endless web framework. Convention over configuration. Using Ionic also leverages my personal experience with AngularJS and web technologies, to boot.

Ionic is an all-in-one, batteries-included solution. It promised the moon. I was excited.

Outcome

I immediately loved using Ionic because it was so painless to get going. It was nice. But — read between the lines on the Ionic homepage! — it’s meant only for hybrid mobile. I thought I could fudge the web experience out of it as well, but alas, the more I tried the more frustrated I became of how mobile-centric the whole framework is. (For example, no css hover styles, because they aren’t needed on mobile). Not exactly a shortcoming of Ionic, rather a shortcoming of my choice of a tool ill-suited to my needs.

If in doubt, just try something. Choosing to go ahead with Ionic allowed me to clarify my requirements, so I wasn’t too upset about having to switch horses mid-stream. I realized that, for better or worse, I was a desktop rather than a mobile device kind of guy, and it just felt right that my product needed to work, at least initially, on a desktop browser.

It’s still possible that in the future I may revisit Ionic and create a hybrid mobile app, but for now I needed something else to move me forward.

So, back to the agony.


Web Stack the Second

(circa November 2015)

Rationale

I again chose another all-in-one, batteries-included solution, Meteor. This time, one that was meant for web applications. This decision was made after looking at the current state of the Javascript ecosystem, and once again running away in fear, trying desperately to avoid having to make a hundred different choices of technologies.

Case in point: On a previous project, I spent a lot of time configuring and crafting a Gruntfile, to be used for scaffolding hundreds of projects. Although the end result is satisfactory, the process of integrating two dozen grunt tasks so they all play nicely together wasn’t exactly fun. It’s time spent NOT working on my project, but rather working on the machinery for building my project. Ugh. I wanted to avoid all that.

Having chosen Meteor, I still had to make a couple of decisions on my own: I chose to use Angular-Meteor and Semantic UI.

I picked Angular-Meteor because I didn’t want to learn yet another thing (Blaze) or jump on the latest bandwagon just yet (React). Besides, my Ionic prototype would need to be ported over to this new web stack, and it was already using AngularJS.

My decision to use Semantic UI came later on. It seems to be a sane alternative to the most popular choice of CSS frameworks, Bootstrap. I’ve had some experience with Bootstrap, and it was satisfactory. I had the appetite to try something new. Until choosing Semantic UI, I was writing CSS from scratch, which is a worthwhile pursuit but it was slowing me down, especially when it comes to dealing with form controls. (Who likes writing CSS for form controls? Nobody.)

Outcome

With Meteor, I type “meteor” on the command line, and it’s all unicorns and rainbows! Awesomeness. It actually works really well.

Angular-Meteor turned out to be a workable solution as well, although one that feels a bit like Mr. Potato Head (attaching a strange appendage onto a body).

Another thing I love about Meteor is that it doesn’t use REST. I’ve always felt a gut aversion to REST APIs for communicating between the client and server of a web application, and I still don’t know why that is. With Meteor doing its magical DDP thing, guess what, I don’t have to worry about it!

However, all that magic does have a cost. A minor case in point: One thing that wasn’t immediately clear — forgot to read between the lines again! — was that deploying Meteor isn’t that straightforward. It’s not too hard either, but there is a lot of magic going on under the hood.

Unfortunately, the minor point was soon eclipsed by a major point. Somehow I must have missed the part about Meteor being exclusively useful for SPAs (Single Page Applications). And from nowhere, out pops another requirement which had been hiding from me all this time: My project consists of an SPA, and also some other static and dynamic pages! In other words, my project has an SPA, rather than my project is an SPA.

After some googling and reading articles such as this one and this one, and especially this one, I again had that uneasy feeling in my stomach that I would have to face the agony, again. All the proposed solutions for server-side rendering with Meteor seemed to me to be hacks or otherwise too complicated.

Is it really so complicated? All I’m looking for is a way to serve up a few pages of static content, and a server-side rendered home page. The key requirement is that it needs to be server-side rendered because a) it’s better for search engines and b) it’s way less bloat. Of course one could argue that Google is getting better all the time and can even index JavaScript now, and who cares about bloat which is just another word for premature optimization. But intuition tells me that those things still matter. I didn’t want the SPA portion of my project (which is geared to a small set of users) to load when displaying the home page (which is aimed at the masses), and yet the home page still needs content which comes from Meteor’s MongoDB.

Here’s the realization: Meteor is designed for SPAs, and when the Meteor community talks about server-side rendering, they take it to mean, server-side rendering of SPAs. Meanwhile, I am more interested in what you might call traditional server-side rendering.

So it’s back to the agony: choosing a web stack again.

Questions: Should I abandon Meteor altogether? Should I pick a language other than Node.js/JavaScript? Why is this all so hard? Back in the day, Java servlets worked just fine for serving up dynamic pages rendered on the server-side. Now, with all this fancy Node.js stuff they seemed to have completely forgotten about this most basic of use cases. Or perhaps I’m just missing something about this new isomorphic paradigm I keep on hearing about.

At any rate, after a painful day of Googling and getting nowhere, I still have a project to build now, and a problem to solve now: I needed a reasonable server-side rendered non-SPA solution.


Web Stack the Third

(circa February 2016)

For the SPA: Still using Meteor, Meteor-Angular, and Semantic UI.

For the public facing website:

That’s right, a Node.js web stack that uses no framework at all. Finally, I’ve come full circle, and have resigned myself to living within the chaos and the fragmentation which is the npm ecosystem. I have to find and integrate all the bits myself.

I also accept my fate of having to learn another templating language, Jade, Since Angular on the server-side would be another whole ball of wax.

Now the agony of a hundred decisions begins:

  • How do I scaffold my webapp? Yeoman’s generator-webapp, because it’s popular and seems reasonable.
  • What is my build system? Gulp, because it’s the default that comes with generator-webapp. Again, popular and seems reasonable.
  • How do I scaffold Express? Express-generator, because hey, it’s made by Express, so it can’t be all that bad, right?
  • How do I connect to Meteor for data? There seems to be at least three options: 1) Expose Meteor data via a REST API, 2) Connect to Meteor using a DDP Client, or 3) Query directly against MongoDB. I chose to go with 2) because it seemed the cleanest.
  • So, which DDP Client? Seriously? Meteor DDP Clients for JavaScript offers not one, not two, but three possibilities: ddp, ddp.js, and asteroid. Asteroid is the most appropriate choice (how is one to know that without investing in a lot of research?)

What’s a good analogy for what’s happening here? If web frameworks were vehicles, then the npm ecosystem is a marketplace for vehicle parts. So, my situation would be like having a Mercedes (Meteor) in the driveway, and having to build a go-kart (custom Node application) on the side, because large pieces of lumber won’t fit into my Mercedes, and nobody’s selling new pickup trucks (Node framework for server-side applications). They are selling old pickup trucks, but who wants one of those? (Spark or Play for Java, Ruby on Rails, Django, etc. — these would work just fine, but they come with their own baggage. I wanted a Node framework to try to stay as similar to Meteor as possible.)

Conclusion

What an ordeal that was! Now I can actually go back to working on my project! I hope you have enjoyed the read and learned something from my thought processes and experience. Maybe it’s time for me to build my own framework… with you know what. Or not.