- The post is about why, when Clef was deciding whether to use React or Ember to build Instant 2FA , we went with Ember.
- Ember F astBoot enables server side rendering in any Ember app with one command.
- Because of the way Ember enforces conventions, these addons almost always work out of the box.
- One of the goals of Ember is to give the developer the best experience currently available without having them do any work (or as little as possible) .
- We haven’t had to do (2) but it seems much simpler in Ember with Ember addons.
One month ago, we started working on a new product: Instant 2FA, the easiest way to add two-factor authentication to any site in less than an hour. Currently, whether you roll your own two-factor…
One month ago, we started working on a new product: Instant 2FA, the easiest way to add two-factor authentication to any site in less than an hour.
Currently, whether you roll your own two-factor with Google Authenticator or use an API service like Authy, a standard integration often takes weeks.
With Instant 2FA, we’re building a solution that reduces the entire integration to 3 API calls and provides everything out of the box: Google Authenticator, SMS, and Yubikey support; remember this computer; rate-limiting and alerting; and with our first few customers, we’ve done the integration in a development environment in less than an hour.
This blog post outlines our thinking behind choosing Ember (a technology none of us had ever used before) over React (which we’ve been running for 2.5 years in production at Clef) and our reflections on the decision after one month of work.
Every new project requires a million technology decisions. Luckily, 4 years of company experience building Clef, a two-factor product used by nearly a million websites, made most of our decisions obvious. We knew our backend services would be built with Python, SQL, and Flask, leveraging all the tooling and libraries we’d spent years working on.
The frontend, however, was a different story: we’ve been using React and flux (powered by reflux) in production for two and a half years, but as we began considering how to build Instant 2FA, we wondered whether using a more fully featured framework like Ember or Angular would be a better decision.
When we started considering Ember over React, there were two main hypotheses that drove our curiosity:
As we dug into each of these hypotheses, we found compelling evidence that ultimately led us to choosing Ember for both our applications.
Over time, this gradual composition of libraries cemented into our own little incarnation of the React ecosystem. Different libraries duplicated each other, but things worked. We used:
A few months ago, we did a little side project where we had to create a client application from scratch. We went with React for the view layer, but given the dramatic evolution of the surrounding ecosystem over the last few years, we ended up with a very different composition:
It was fun to get to pick and choose, but every step of the way we doubted our choices: were we making the wrong decision with a given library choice? We were “configuring” our own framework from the tools available in the React ecosystem, but had major concerns about whether our configuration would help or hurt us.
As we started working on Instant 2FA, the thought of Ember making all these decisions for us — enforcing a convention over configuration — was very alluring. Some of the decisions we were most excited about not making were:
Ember ships with testing built in and tests are auto-generated when new units (models, routes, services, serializers, etc) are created. For the last React application we built, we’d spent days setting up test harnesses, acceptance tests, and all of the other tools necessary to have a fast, easy-to-use test suite, and we still were constantly frustrated with our setup. Ember built acceptance and unit testing into the framework, which we hoped would make it easier for our code to be tested at every level.
). This toolchain comes with sane defaults out of the box (ES6 and modules, for instance), but the community built around this standard is the most powerful part.
In our previous setups, every time we needed to change our build to implement a specific goal, we needed to write custom code. One great example of this is uploading sourcemaps to Sentry when our code is deployed. In our React apps, we did this in a shell script after our webpack build was done.
there were established patterns for how to do things — even if some of those patterns felt a little outdated.
Ember FastBoot enables server side rendering in any Ember app with one command. Having explored server side rendering in our previous React apps, we knew that for every configuration of libraries around React there was an equally complicated server side rendering setup. Server side rendering wasn’t something we needed out of the box, and we still haven’t enabled it, but knowing that it’s a cli command away, rather than a major project away, is a weight off our shoulders.
After outlining and exploring all the decisions we would need to make if we went with the React ecosystem, taking those decisions out of our hands, and putting them in the hands of a core team and community that has been building client-side applications for years, became an obvious choice.
. For each new iteration of progress at the conceptual level, a new library or tool needs to be added to your toolset: or tying this back to the language of progressive enhancement, the developer has to do work or change their tools to get the best experience.
In contrast, one of the goals of Ember is to give the developer the best experience currently available without having them do any work (or as little as possible). Take the same example of uni-directional data flow. While Ember 1.0 existed before this pattern became well known, as the concept grew in popularity and conceptual clarity in the React & flux ecosystem the Ember core team started figuring out how they could roll it back into Ember. With Ember 2.0, and the gradual shift from controllers to components, uni-directional data flow has found a home in Ember without Ember developers needing to add new libraries or adopt major conceptual paradigms. It may have taken a little longer to get to this enhancement — but when it came it was well thought out, built into the framework they already used, and there was a straightforward migration path. This is a perfect example of how Ember employs Progressive DX to give its developers access to the latest patterns and tools!
Reading the core team’s work during our evaluation period, this theme of Progressive DX felt consistent: features like Ember Fastboot (server side rendering), glimmer (faster rendering enginer), routable components (uni-directional data flow), and services (isolated cross cutting concerns) are all examples of how the Ember experience has been progressively enhanced, often borrowing directly from patterns other frameworks have introduced, to give Ember users the best of the web.
At the beginning of a project that will last for years, it’s comforting to know that we have a team working to integrate the latest and greatest into the tools we already use, so we don’t have to search for it ourselves.
One month in, we’re very happy with our decision to use Ember. It’s still early, but overall, our two hypotheses have held — we’re enjoying following conventions defined by more senior engineers and are already benefiting from different ways Ember has progressively enhanced our experience.
Ember is sweet. Really easy to pick up enough to design well, and I really love using css-modules.
We’ve also found a ton of other, smaller reasons to love Ember.
command. After working with the framework for a little more than a month, it’s one of our favorite things: having a canonical way to generate any unit of logic (model, route, service, etc), means there’s no cognitive overhead to writing many, small, easily testable units. It also means that whenever a unit is created, a test is auto-generated for it, so developers have an even easier time testing their code.
, it’s even easy to generate complex relationship setups, which has historically been a challenge in our development workflows.
template in every template folder. When data is loading, or loading fails, Ember will automatically render the respective loading or error template closest to the route the user is currently on. This lets you easily add a top-level loading state, then add specific loading states throughout your app where necessary. It’s beautiful!
Of course everything hasn’t been perfect — learning any new framework is a challenge and migrating from one framework to another always brings some amount of frustration with the different paradigms.
Hot-reloading and time travel debugging are two of the most useful tools that have come out of the React ecosystem.
With hot-reloading, when you change code, the logic is reloaded in place, without requiring a page load. As a developer, this means you don’t need to navigate back to the point in the page — with the appropriate state — where you were working every time you make a change. Instead, the logic just refreshes and you can keep on working.
With time travel debugging, it’s trivial to see how state in your application changes over time, and jump through those different states. This makes it easy to diagnose and fix bugs that come from complicated state manipulation!
Not having access to these tools is sad, but not the end of the world.
In our React applications, styling components was always a point of frustration. This boiled down to two primary issues:
In the Ember eco-system, (1) seems similarly unsolved: we’ve gone with css-modules for styling components, but have had to do contortions to make it work with a base styling system (like foundation). We haven’t had to do (2) yet, but it seems much simpler in Ember with Ember addons.
This post isn’t about whether Ember is better than React. This post is about why, when Clef was deciding whether to use React or Ember to build Instant 2FA, we went with Ember.
There are an infinite number of ways to build a web application and there are an infinite number of reasons the right decisions for our needs could be the wrong ones for you. This diversity of options is what makes the web evolve so fast — and what makes it so powerful.
We hope you learned something from our thought process — and we’d love to learn something from yours. If you’ve made the same choice, we’d love to hear why! If you’ve made a different one, we’d love to hear why too!