Javascript Frameworks: A futile attempt at objectivity

A personal view of the current state of JavaScript frameworks

I’ve written the same article three times now. The first was written essentially as someone advocating all frameworks uncritically. It featured blind support and unquestioning promotion. The second was someone slamming the frameworks overly critically. It featured goalpost shifting and misconstruing of framework goals.

The actual point was to raise the fact that all framework discussions involve subjectivity and “spin”, and acting like they don’t does no one any favours. Nevertheless, I found a few people using that post as some sort of basis for actual recommendations. I don’t think that’s helpful.

This version has something the other two don’t have: honesty.

Perhaps a better way to put it would be to be honestly subjective. I have my own biases and preconceptions, but I want to state them openly and then make a sincere attempt to discuss other frameworks. I’m also trying to discuss these not with reference to myself but to a large degree as whether I recommend them to someone learning.

This will be a combination of the previous articles, but it goes beyond just splitting the difference. Some “issues” previously stated aren’t really valid concerns, and some of the benefits are more theoretical than realised in practise.

I wanted to write this article because I felt that the conclusions people made were drastically different to the intent previously. So many people thought I was sincerely pointing out flaws in JS frameworks. I was told I should “make my own” or had people say “Finally, someone says it! That’s why I don’t use frameworks!”

I’m not going to argue my opinions here. They’re just that. I’ll happily engage with people, but there’s little point trying to convince me yet again that JSX is a good idea.

Angular 1 | Angular 2 | Aurelia | Ember | Meteor | React | Vue

Angular 1

Angular holds an interesting place in webdev now. The fact is, Angular 1 is still a commercial reality. If you look at Return on Investment (RoI) for technologies, the RoI of things like Angular are through the roof. While commentary and advocacy fall precipitously, the actual usage of technology by business are higher than ever. Its edge-case problems are solved, it has a wide range of tooling and knowledge, well documented with learning and training resources, and has a crapload of skilled and experienced developers in a pool.

Like many people, Angular was the first framework I learned - discounting jQuery which we called a framework in our ignorance. Like many people I don’t actually like Angular much, but I disliked it before it was cool.

I am not a big fan of its syntax, which modifies html to invalidity it its idiomatic form. My previous criticisms remain valid, Angular’s idiosyncratic patterns and terminologies are a bad idea.

But at least in my area, Angular and React are the only commercially viable frameworks. I’d love to advocate against learning it, but it’s simply not a reasonable option. And it’s certainly not just limited to legacy applications. Many agencies and organisations have yet to see any concrete benefit to upgrading their stack, and with good reason.

For agencies and commercial development studios that create a large number of smaller applications over short development cycles, Angular is hard to pass up. In that respect it’s a bit like Wordpress. It might be a bit icky (WP is well beyond a bit) but it’s just as hard to recommend anything else as an alternative to that use case with any sort of objective argument.

Despite what developers think you probably don’t actually really need anything more than OG Angular for the vast majority of applications. Though it’s slow, it’s honestly fast enough for well above the 80% case. Though it’s old, clients don’t pay extra for “modern”. As a known solution to a known problem, Angular is hard to beat. And as a bullet point on a resume, it’s similarly exceptionally valuable.


Angular 2

Angular 2 is sort of a mixed bag. It’s probably fair to say that the reason for its success is largely due to having a magic name. Angular 2 and Angular have little in common beside that and some terminology. While Angular 2 will never have the stranglehold Angular had on the community, there are still a ton of companies who will simply move their knowledge from Angular to Angular 2 without ever looking elsewhere.

There are strengths and weaknesses to Angular 2, aka the needlessly ambiguous AngularJS. Its template syntax is confusing and alienating to an outsider, and the requirement to have case sensitive HTML properties is concerning. However, its strengths are notable, too.

One standout is observables. Angular implements Microsoft’s RxJS Observables, a pattern that while hard to get your head around (and honestly probably not great for simple data access) is excellent for more live and real-time websocket or stream stuff. There’s a fairly good chance that Observables provides absolutely no benefit for your app, but if it’s good fit it might well be a life-saver.

Angular 2 also uses a fork of Ember’s excellent CLI, which really helps getting it up and running, and helps make a productive “happy path”, as well as generating a lot of boilerplate, running tests, etc. Webpack is a good choice.

Typescript is also excellent. When using slightly less chaotic languages, such as C# or PHP the IDE is able to do a lot to help provide insight into what functions are available and how to use them. Typical JS applications lack that, and the IDE can’t get a lot of visibility about how things work, what methods are available and how to call them. Typescript takes that control, knowledge and discipline back. It does introduce a build step, but you’re already going to have to transpile all over the place, so what’s another build step?

One area Angular 2 has definitely misstepped is in its branding. Google are encouraging people to refer to it specifically as Angular, as in the logo above. They’re doing this in large part because they want their releases to be major version numbers without the huge restructure involved in the 1 to 2 transition. Angular 4 is already in beta. However that branding is drastically short of actual information. AngularJS is already what people were calling Angular 1, so trying to make some sort of distinction (such as this article) becomes a muddle. The brand itself is hurt by this. https://angularjs.org/ is for the OG NG, while the new version is handled in https://angular.io/. Nevertheless, it can be difficult to know at a first what version is being referred to in any given context.

Angular 2 isn’t my favourite framework. I like a lot of what it’s trying to do, but it feels like it’s made a lot of mis-steps along the way. Nevertheless, it can’t be denied that as a matter of commercial reality, Angular 2 is impossible to ignore. Many companies with legacy Angular apps will upgrade directly to Angular 2.

If picking up a framework specifically for resume value, and you want something that’s a complete solution, keeping up with the latest Angular is a solid bet.


Aurelia

Aurelia was a surprise for me. It was possibly the framework I knew the least about. I have to say I’m impressed. I’m still an Ember dev by preference, but if I wasn’t using Ember it would be Aurelia I went with.

Aurelia’s core principle is one of minimal intrusion. It aims to facilitate the process of building complex, modern JavaScript applications. As such it focuses on an exceptionally good and clear template binding syntax for components.

Aurelia also supports Typescript natively, though a little less forcibly than Angular 2, treating ES6 and TypeScript both as first-class citizens.

The other thing that’s surprisingly good is Aurelia’s CLI tool. It’s still in beta, but it’s got a level of functionality near to Ember’s own. Unfortunately a lot of it is still quite a bit more manual, but it’s a good step in the right direction.

Aurelia suffers in two areas though. The first and most obvious is adoption. This isn’t a trivial issue, nor an easy one to fix. Finding learning resources, sample code, or troubleshooting tips is far more challenging than an Angular or React app would be. Finding staff is similarly more challenging, but unlike some other frameworks, just having knowledge of ES6 and Typescript would be enough.

The other area Aurelia lacks is that it doesn’t actually do that much. Though the component view model binding thingy is really nice and very intuitive, and the event binding is elegant, there seems to be a lot the framework really doesn’t help out with. There are a long series of imports to manage, etc.

Where Aurelia does try to do things by “standards” it sometimes mis-steps there too. For example, the most “standard” import is SystemJS, which JSPM is based on, but that’s not the module import system the industry has standardised around. NPM with something like Webpack is a much more common approach. It’s almost certain Aurelia’s CLI is transitioning to that, but for now things are a bit uncertain.

I said I’d be honest, and the fact is I don’t know Aurelia well enough to really be effectively critical. Unfortunately, given its current position in the industry it’s hard to justify learning more. I already have Ember as a great integrated solution, and React for smaller components. I can approve of and advocate Aurelia, but it’s unlikely I’ll ever be a significant user of the framework.


Ember

I make no secret of my support for Ember, but I want to very quickly say why. It’s not because it’s hard or complex or powerful. It’s because it’s fast and easy to develop in.

Where Ember really excels is its workflow. Everything is driven from an incredibly powerful CLI, that eliminates or trivialises build tools, dependency management, testing, and more. Scaffolding is a single command. Test execution is a single command, including unit tests, integration, and acceptance tests with a full test harness in the command line. Boilerplate generation is a single command, and auto-generates test stubs. Dependency management is a single command that loads npm and bower dependencies, imports resources, and updates the build tool to implement the new requirements.

It’s interesting, then, that it has a perception as being “difficult”. I’m not sure that’s actually a reasonable conclusion if looked at comprehensively. The actual framework API might be relatively large, but there’s near zero configuration or tooling complexity. There has also been absolutely no “churn” in that space, freeing Ember developers from the trials of the Grunt, Gulp, Browserify, Webpack procession.

The more valid (and quantifiable) criticisms include ones on performance and size. Ember is a large platform. It contains a lot of stuff. There are projects within Ember that aim to reduce that size. These include addition of “tree-shaking” unused code, svelte builds to remove deprecated code that isn’t required, and module syntax to split Ember’s large central namespace to facilitate the above.

Ember’s rendering engine was recently rewritten in TypeScript, for significant performance and productivity gains, and slow bits of Ember will doubtless see the same process occur.

I’d like to see that. I’d like to see Ember faster, and smaller, but without overly compromising its accessibility. But at the same time, I don’t feel that performance for its own sake should be the altar we sacrifice productivity on.

Ember needs to (and will) get faster and lighter, as the core devs are focusing closely on mobile performance. It’s worth noting that the whole of Ember now is the same speed as React with MobX state management.

Where Ember has struggled recently is sticking the landing. It has some amazing and much needed features in development. Angle bracket components are a perfect example. They were implemented in 2.10, but the feature pulled because it turned out to have some nasty edge cases. Now it’s in limbo. Fastboot trivialises Server Side Rendering in a stunningly well-thought-out package. But it’s in limbo. Svelte Builds are in limbo. Changes to module import approach, unified testing, and other major features are in limbo.

A lot of these are for very good reasons. Glimmer 2, an entire drop-in replacement for the rendering engine has just released, and many of these features were held up by that. I’m very optimistic that with this in place, Ember’s team can start landing features like it’s the end of Die Hard 2.

Ember is my preferred framework. There are a lot of reasons for this, enough for a whole separate article. The core of it is that Ember’s approach matches my perception of the problem I want a framework to solve. It has a workflow that lets me focus on application development, rather than build tool busywork.

When I come at something with Ember I feel like I’m carrying a full tool box. Sure, the box is “heavy”, but it’s got the tools I need to do amazing things. And most critically it makes the difficult things very easy.


Meteor

Meteor was the opposite of Aurelia for me. I went in with an overall positive impression of Meteor I expected to solidify. Meteor’s intent is commendable. A consistent cross-concern, full-stack framework with optimisations for realtime data sounds ideal. But I couldn’t have been more wrong.

The more I’ve looked at and played with Meteor, the less impressed I’ve been. The original goal seems to have diluted in a number of compromises. The introduction of React to the front-end in place of Meteor’s own templating seems to be a nod to the progress made in web development. But if making a frontend with React, it’s hard to really see what Meteor is bringing to the table.

What it’s bringing is DDP. DDP is Meteor’s unique PubSub system for events and data. There are good things about DPP, no doubt. Because it’s a pub sub system, it’s ideally suited for realtime applications. What it’s not suited for is anything else at all. Every other JavaScript framework is backend agnostic. It doesn’t care whether you’re using PHP, Ruby, .NET or Elixir.

But a Meteor app can’t be agnostic. The backend can’t be replaced out, its idiomatic approach won’t work with anything but Meteor. Or React with special bindings. But the REST standard approach that works with every other framework, that’s optimised, well discussed, and easily mocked, tested, reused, shared, and documented isn’t an option for Meteor.

As another criticism, some of the things that should be easy are not, in particular, Server-Side Rendering. Ember’s implementation of SSR requires two simple entries on the command-line. Vue’s requires a simple wrapper around standard objects. AngularJS’ implementation is honestly kind of awful but at least well documented with a whole dedicated sub-site.

This is Meteor’s implementation: ¯\_(ツ)_/¯

With both the back and frontend under Meteor control it should have the most mature solution, but it has the least. Searching for Meteor implementations bring up hacks, tests, and articles that are at best old and at worst flatly wrong. Everything but a comprehensive, simple, production-ready solution.

The twin routers thing is also quite inexplicable. It’s difficult to find Meteor sample code, but what’s available always has one thing in common: an enormous router.js file. I’m not sure if “Fat Router” is an official anti-pattern, but perhaps it should be.

I want to like Meteor, but there seems to be no reason to recommend it against literally any other framework.


React

React is interesting from an industry point of view. For a long time it was the lone alternative significant alternative to Angular. More particularly it was the modern option, and felt for most developers like the way forward. Its “component” driven structure was new and revolutionary at one point, but now the default.

React solved only a small segment of the problem, specifically the process of binding the model to the view. React itself doesn’t support routing, or state management, or a wealth of other functionality. It’s not supposed to. But that means React isn’t a framework, but a widely varying stack solving the same or similar problems. React more than anything legitimized and required the tangle of build tools and task runners that we take for granted today.

The library has undoubtedly been used to create amazing tools. Netflix is a React app. Companies like Uber, AirBnB, Wix, and so on, React, React, React. It’s undoubtedly the darling of startups. Infinitely flexible, ultimate control.

But that control and flexibility comes at a cost. The difference between being able to choose a component and having to choose a component is nothing but wording. React as an ecosystem is a staggeringly fragmented one, across half a dozen build tools, hundreds of components, test approaches, starter kits, architectures and solutions. So many starter kits.

React has, for example, a CLI tool. But unlike the other options presented here it’s pretty nothing. It just sets up webpack with some reasonable defaults. That’s it. It eases the bump of the initial build setup, but only by the least it possibly can.

A React developer has to manually, consciously, and explicitly add functionality that an Ember, Angular or Aurelia developer takes for granted. Even a router. And it’s at that point the performance advantages React has long touted start to disappear. The most recent JavaScript framework benchmarks still showed Ember as approximately the slowest. But the newest Ember performed identically to React with MobX state management, and very close to React with standard option Redux. How many packages and addons before React is actually less performant than the monoliths, while still bringing less to the table and carrying more baggage in their solution setup?

Worth noting that’s Ember specifically. Angular 2 and Aurelia are both already vastly faster, while still providing extensive functionality.

It would be impossible to talk about React without talking about JSX. This is highly subjective. I hate JSX. I think it’s awful. Maybe I’m old and those days are long gone, but I’ve spent two decades being told that you do not output markup from a function. And I’ve spent a decade laughing at Wordpress and pointing derisively at the fact that it does that. To come along and say all the rules are different and separation of concerns no longer matters…

And yes I know the cookie cutter response is that’s not separation of concerns it’s separation of technologies but I refuse to respond to that because it’s made up nonsense to distract from the fact that your JavaScript is full of HTML markup.

And I also know that it’s not really HTML and it’s syntactic sugar over render functions, but it’s the abstraction that’s the problem, not the underlying code so that answer is just like saying PHP’s API is fine because it’s all magnetically encoded ones and zeroes.

None of this should be taken as a dismissal of React. I actually have an enormous respect for it as a library and as an ecosystem. It’s impossible to deny that some of the most talented developers in the world are doing amazing work in React. It has an assured place in the development world. As a career pick it would be nearly impossible to find a more broadly used technology option.


Vue

There’s little reason to distinguish, so all discussion here will focus on Vue2+. Vue is amazingly and impressively fast. I’d be interested to see how it scales with dependencies, but it’s definitely a performer in its pure form. It’s also got some elegant solutions of difficult issues, notably Server Side Rendering. Elegant solutions to difficult problems are, to my mind, the key purpose of a framework.

Where I have issues with Vue is its messaging. Vue proposes itself as a progressive framework. What that means is that Vue is intended to be as easy to use as something like jQuery, pulled in from a CDN. And then can scale up to any sized solution.

But there is a lot of hand-waving involved in that scaling up process. For example, nearly all other frameworks make a default approach of some form of build process. Ember and Meteor include it as part of their default workflow. React cheats this process by making its official “getting started” code a pre-configured codepen. But all other frameworks seem to acknowledge that separate modules compiled and built by some process is the only valid way to do modern JavaScript. Only Vue pretends there is some other option and maintains this fictional CDN workflow.

This means that only Vue has a “make it actually work properly” step between initial demo application code and actual production code. Way too much of Vue’s documentation and branding focuses on how “easy” it is to get started, leading to some underpants gnome presentations.

Vue excels at solving simple problems, but for solving difficult problems it seems to be lacking. As a perfect example, Jeffrey Way of Laracasts does an excellent series of tutorials on VueJS. We’ll set aside for now the fact that it takes sixteen episodes before he touches on an actual typical workflow, and twenty six to get to a router. But in the actual content it takes more than seven minutes of a twenty minute video to even get a working router. There’s a lot of discussion, for sure, but the number of steps involved is enormous.

As another example, I saw an article on Reddit of how to implement a pub/sub system in VueJS. It was an advanced tutorial, thick with code. Which immediately prompts the question, if you want this why would you not use a framework that already has this functionality, or a similarly advanced eventing and action system?

Vue’s developer Evan You did an excellent presentation recently where he discussed the difference between what he termed Inherent Complexity and Instrument Complexity. Specifically, the difference between how hard the problem is to solve, and how hard it is to manage the solution.

He rightly pointed to Vue as a tool with low Instrument Complexity for solving problem with low Inherent Complexity. He then speaks of how it can also solve problems with high Inherent Complexity, without really mentioning what happens to the Instrument Complexity at scale.

To carry on the metaphor from Ember about toolboxes, I feel like using Vue is just showing up with a Leatherman and acting like that’s all you’ll need.

Hey, look, I have a screwdriver and pliers. And if I need a hammer I can just get one from the shops. And then later I’ll get a saw. Why carry so much stuff? It’s just bloat! I have my Leatherman. It’s a progressive tool box.

The Laravel connection is an interesting one. The prominence of Laravel in the PHP community is a big driver of the visibility of Vue. Vue’s best learning resource is probably Laracasts. Vue bindings are now exposed by default in Laravel. Where Vue needs to be used as an augmentation on an existing Laravel-driven application that’s an entirely reasonable approach. But for the difficult problem - Single Page Apps - the pattern is a disaster. A SPA is much better done as two separate apps, two separate repos, with two separate sets of tests, two separate deployment strategies, etc.

Vue’s weakness is its workflow. It has the single worst CLI tool, for example. Advocates praise it because it’s flexible, but because it provides no reasonable defaults it forces the developer to determine - in advance - what requirements they’ll have and what template is appropriate. Do you want browserify, or webpack? What are the consequences? Simple, or full? What do you gain or lose with any of these? Finding out is not trivial. React might offer very limited functionality in react-create-app, but it rightly assumes a webpack build, babel transpiling, development server, etc.

Vue is young. It will probably mature over time. Vue developers will start to focus on how to solve questions about maintainable and stable software delivery, rather than how easy it is to make a button. They will start to worry more about the poor testing experience, or how to consistently model domain entities than the number of milliseconds to insert 10,000 rows to the DOM. This is an inevitable part of the Gartner Hype Cycle, current high visibility will translate to a more mature platform focused on best practices and production, rather than the “getting started with” and trivial examples.

It’s difficult to tell whether Vue’s high visibility will translate to high business adoption and actual usage in production project, but I honestly suspect it will.


Conclusion

All of the above is one person’s opinion and nothing more. Where it’s written as a fact is simply a matter of writing style. There’s nothing worse than reading every sentence starting with “in my opinion” and “I think” and to expect that in a published blog is completely absurd.

That said, it’s interesting that my opinions align reasonably well with industry giants Thoughtworks. Their tech radar advocates only two frameworks to their unconditionally recommended Adopt status: Ember and React. Vue and Aurelia are both in the lowest neutral status of Assess. (The category between is Trial.)

MeteorJS sits at the very lowest status of Hold, for technologies not recommended for use:

We think the idea is great, even if the framework is not yet ready for primetime.

Not yet is telling. The description has not been updated in years, suggesting the view is unchanged. AngularJS sits in the same Hold status, and curiously no distinction is made between Angular 1 & 2, though I feel this is an oversight that will be rectified in their April radar release.

Thoughtworks is a business-focused consultancy that steers well clear of the bleeding edge favoured by enthusiasts and advocates, which in my mind makes it a good guide to long term value.

One factor people rarely consider in choosing a JavaScript framework is what backend it has to connect to. In theory, this isn’t relevant. A RESTful API will work identically regardless of implementation, nor would the framework even know.

Still, there is some alignment of backends and frontends, with advocacy, assumptions, and community support. Ember is very popular in the related worlds of Ruby and Elixir. Aurelia has strong support in the .Net community. Node and Angular have long been tied by the MEAN stack, though Angular is big enough not to be constrained by that. Vue is a default installation with the Laravel framework for PHP. All of this may affect the visibility or viability of the framework.

The intent of this article was to simply provide an actual, honest opinion based on my study and experience with a range of frameworks. It was to serve as the sincere discussion and recommendation the previous articles absolutely should not be taken for.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.