To be completely transparent, I'm heavily biased towards Ember. With simplabs, I founded what is now the leading Ember consultancy in Europe. We've helped many teams successfully build, evolve and maintain large applications with Ember over the years. Some of our team members are involved in the Ember core team and we maintain a number of widely adopted libraries in the ecosystem. We're one of the official sponsors of the framework even. With all that experience and also some experience with teams using other technology stacks, I think we do have a view on frontend development that's maybe a bit different from other teams' views and because of that, it is worth sharing.
I think that complexity is fetishized in the frontend world in a way – mainly due to two sentiments. One is simply ego. As the virologists and epidemiologists say (and we all have learned in the past year), "there's no glory in prevention". And just like that there's (surprisingly) little glory to be found in steadily shipping real product value based on solutions to common problems others have found before you and encoded in frameworks based on strong conventions. On the other hand, there's all the engineering glory to be found in figuring out the best™ way to address a particular problem and taming low-level complexity even if all that work is not contributing to executing on a product and business vision – taking on such problems is often done for the glory alone, regardless of whether the problem has been solved before or even poses a challenge in the respective project at all. Having ported a React app step by step from Redux over MobX to hooks and beyond over the course of the past few years likely was an exciting engineering journey and came with a whole bunch of interesting and challenging work. However, the cost-benefit relationship of all the time spent on the endeavor might be questionable.
Chris Manson from the simplabs and Ember Learning Core teams recently told me the story of an engineer he was talking to at a conference. They understood and completely agreed with the value that Ember provided as a full-featured, batteries included frontend application framework that enables teams to build skyscrapers starting from the 20th floor instead of beginning with laying the foundation. Yet they said they would never propose the framework to their boss because then they wouldn't get to write as much code for solving low level problems they found particularly exciting because "Ember does it all for you". While that can be a valid reason not to choose a technical solution at times, in most cases shipping is important and should be the main driver for decisions.
The other sentiment that I believe contributes to the complexity fetish is a desire to be in control of ever every single aspect and detail of one's app. That might be driven partly by the Node community's – highly questionable in my opinion – love relationship with micro packages where applications are made up of a carefully assembled combination of tiny libraries that perfectly cater to a particular application's very special needs – or in most cases, the personal preferences of the engineer(s) setting up the project. Many teams I've talked to over the years have strongly held opinions about what particular routing library they need, why they cannot use the state management patterns of framework X but have to use a different micro-library etc. And while many of these arguments will make some sense from a purely technical point of view, the practical impact is more often than not neglectable or irrelevant even. What's certain though is that all the time and effort spent on assembling (and then maintaining) these highly customized ad-hoc frameworks is not going into building and improving real products for real users.
Contrary to that, Ember takes these low level and mostly unimportant bike-shedding decisions out of the hands of developers. It is a full-featured, batteries-included framework and like similar solutions for the backend like Ruby on Rails, it provides everything one needs to build an app in a coherent way with a consistent API where the individual parts all work together seamlessly since they were meant to work together from the beginning. Because of that, it doesn't allow the level of freedom and fine-grained control over every little detail that many are looking for in the frontend world as mentioned above. And while that might sound unappealing to many, it's actually its biggest strength as it allows teams to focus on executing on their product and company vision and shipping real value for their users.
Frameworks like Ember are all about reducing the amount of accidental complexity that the developers have to deal with. Since Ember takes care of all or the vast majority of aspects of the application that are not an essential part of the particular application's problem domain (e.g. routing, data loading, etc.), it takes all of the accidental complexity associated with these aspects out of the hands of the developers. They instead can focus on tackling the essential complexity only. Clearly separating the aspects the developer is in control of from everything else is therefore a liberating constraint – it liberates developers from getting side-tracked and spending time on non-essential aspects and enables them to spend their time and effort where they truly add value. In contrast to that, building on micro packages and aiming for fine-grained control over all of an application's aspects will necessarily resurface all the accidental complexity associated with those and put the responsibility for them back into the hands of developers. They now have to deal with webpack configurations, integration between packages, etc. All effort and time spent on these tasks are not going into delivering product value for real users.
At simplabs, we have seen many teams struggling with all kinds of problems in web projects and helped them overcome those. In none of those cases were those problems caused by how frameworks like Ember or Rails handle the non-essential aspects of applications. Most of the time what leads to problems is teams struggling to organize code in a maintainable and extensible way in areas where frameworks leave freedom and do not provide strong conventions (typical examples being shaping and orchestrating components in Ember or organizing business logic in Rails apps) – in fact, the worst kinds of problems typically arise where teams build their own extensions to frameworks that add large amounts of accidental complexity and create more problems than they solve. I have seen at least eight different approaches to organizing business logic in custom constructs in Rails apps during my career and every single one eventually lead to a dead end. The same can be said for inventing custom data management libraries instead of relying on solutions like ember-data or Orbit.
With Ember, we have built a consistent codebase of a couple apps and and addons. It is shared by 25 front-end engineers, spread over a few teams. In an early phase, we could focus on providing new features for our clients. Later, while keeping this focus, we could evolve the codebase in a non-disruptive way.
Ember and its ecosystem have given us enough stability to invest in our product and in the development of our engineers' skills.
Cyrille David, Head of Front-End, Qonto
The fact that Ember hides most of the accidental complexity and takes control over these aspects of applications doesn't mean nothing can ever change in the framework and no progress can be had. There is steady and substantial progress in the framework but Ember shields developers from having to deal with the involved churn as much as possible. Instead, Ember constantly ships improvements in backwards compatible minor releases with clear upgrade paths, following its release strategy which emphasizes stability. That allows teams to keep up with recent developments and benefit from innovation in the frontend field while minimizing the incurred cost like the team at CLARK:
All changes to Ember itself go through the RFC process, are validated and tested in real apps through the canary and beta releases before being rolled out to the community. Once that happens, the previous APIs will remain available but be deprecated along with extensive documentation for migrating to the new paradigms (and in many cases there will be codemods even for automating the task; there's also a dedicated app listing the changes between two versions and the changes necessary for upgrading). So instead of every single team paying the cost for exploration and experimentation, the framework and community pay that cost once, for the entire community to benefit afterward. That's what the Ember community also refers to as the safety of the herd.
And Ember has seen many substantial changes to its core concepts over the years:
Each of those changes were substantial updates to the Ember programming model. Yet, each one was released in a way that made it easy for the entire community to follow along. The entire ecosystem revolving around a single defined set of techniques and practices while making sure no project is left behind and stuck on old patterns prevents fragmentation. Everyone in the community has a collective interest in supporting, maintaining, and evolving the same set of tools and the entire community will collectively make sure those continue to work and work well for everyone using Ember. There is no risk on individual teams and projects being left on their own because they bet on the wrong horse that ends up not being actively maintained so that the teams would either have to take over maintenance themselves or switch to a different solution which would often result in large refactorings, again directing time and effort into dealing with accidental complexity rather than essential complexity and generating product value.
As laid out above, Ember is a full-featured application framework that contains coherent building blocks and concepts for all aspects that real-world applications face and that are not inherently coupled to their problem domain. While Ember encapsulates the internals of these concepts so developers do not have to deal with them, all these concepts are still present and contribute to the framework's public API and general architecture that one is exposed to when working on an Ember project. This often leads to criticism focussed on the fact that there is a lot to learn with Ember and some or much of that might not be necessary for a particular project
I just want to build a calculator widget for my static site – why do I need to worry about routing, data loading, error states, etc. for that?
– someone who should have chosen React
Comments like that are hard to counter. Of course, there's no good reason why anyone should have to set up a route structure along with a template hierarchy or understand what adapters or serializers are when the application they are building does not need any of that anyway. In reality, though, this doesn't imply Ember is unnecessarily bloated or overly complex but the complaining person turned to a tool that serves a different purpose than what they need for their particular job in the first place.
Even though the boundaries are sometimes blurry, there still is a substantial difference between static or only partly dynamic web sites (like your favorite news outlet's site or most e-commerce sites) and full-on web apps (e.g. social networks like Facebook or LinkedIn or dashboard-style apps like the online banking UI that Qonto is building). These different use cases also come with different characteristics and requirements in terms of interactivity, (load time) performance, and user expectations. Aral Balkan wrote an interesting post in 2013 on the topic in which he introduces what he calls the "Documents-to-Applications Continuum" – and what he said almost 8 years ago, still applies today. Ember's sweet spot is all the way on the "Applications" side of that spectrum:
There are plenty of other and better options for other kinds of projects (and for static content sites, I'd argue any client-side framework is the wrong choice more often than not anyway – however, admittedly we went through the exercise of completely over-engineering a static site as well to learn that the hard way). The point is, if you're not building a web application, don't look at a web application framework to build it with. Yet, many teams would do that and then be disappointed that the framework they tried does not turn out to be a great fit. To me, that's a bit like complaining SpaceX's rockets aren't great to do grocery shopping with. A rocket not being an ideal choice for that task doesn't mean it's a bad rocket, just that advanced technology designed for tackling challenging tasks isn't necessarily also a great fit for simpler tasks.
Ember has never been the coolest kid on the block and probably never will be. Building on solutions others have found before you isn't a particularly attractive outlook for many developers. It takes quite a bit of experience and reflection to let go of one's vanity and accept that the less you do yourself and the more you build on existing, proven solutions, the better of an engineering job you're actually doing and the better your work is in the interest of the company you build or work for which is ultimately the top priority as it is what's paying the bills and salaries. Ember developers frequently are the highest-paid and most senior in the annual state of JS survey and I don't think that's a coincidence.
Ember has been an enabler of great productivity for many teams for almost a decade and I'm sure it's going to continue to be that. It's changed and improved a lot since its first release and is now in better shape than ever with its Octane edition. All those changes and improvements were introduced with minimal effort for teams to stay up to date and migrate their apps in small steps over time. There also is little to no fragmentation within the community – everyone using Ember.js is basing their work on the same idioms and techniques, all originating from the same highly cohesive ecosystem. And when more changes and improvements are to come in the future, they will be battle-tested before migrating the community, and that migration will take everyone along, leaving no app behind.
Qonto and CLARK are two great examples of teams executing on their product vision steadily and sustainably. The companies are two of the most successful and fastest-growing FinTechs in Europe and have scaled their teams significantly over the past few years while continuing to ship steadily and sustainably. But they are not the only ones using Ember successfully of course – others include companies building ambitious apps with large and growing teams like LinkedIn, Apple, Square, Heroku, Intercom, and many more. All those teams might generate little fuzz and hype but ship product value constantly and will continue to do so building on Ember which will keep lifting them to new heights for the time to come.