Free for 90 days: Sign up now and get 90 days managed free after your first deposit. See offer details

<title>Dismiss</title>
Engineering at Betterment

Server JavaScript: A Single-Page App To…A Single-Page App

Betterment engineers recently migrated a single-page backbone app to a server-driven Rails experience.

Articles by Harris Effron

By Harris Effron
Software Engineer, Betterment  |  Published: April 29, 2016

Betterment recently migrated to a more simple single-page app using a UJS pattern.

As we add more features, we make the code even simpler. This framework also allows newer recruits to onboard faster.

engineering
Betterment engineers (l-r): Arielle Sullivan, J.P. Patrizio, Harris Effron, and Paddy Estridge

We recently changed the way we organize our major business objects.

All the new features we’re working on for customers with multiple accounts—be they Individual Retirement Accounts (IRAs), taxable investment accounts, trusts, joint accounts, or even synced outside accounts—required this change.

We were also required to rename several core concepts, and make some big changes to the way we display data to our customers.

Currently, our Web application is a JavaScript single-page app that uses a frontend MVC framework, backed by a JSON api. We use Marionette.js, a framework built on top of Backbone.js, to help us organize our JavaScript and manage page state.

It was built out over the past few years, with many different paradigms and patterns. After some time, we found ourselves with an application that had a lot of complexity and splintered code practices throughout.

The complexity partly arose from the fact that we needed to duplicate business logic from the backend and the frontend.

By only using the server as a JSON API, the frontend needed to know exactly what to do with that JSON. It needed to be able to organize the different server endpoints (and its data) into models, as well as know how to take those models and render them into views. For example, a core concept such as “an account has some money in it” needed to be separately represented in the frontend codebase, as well as the server.

This led to maintenance issues, and it made our application harder to test. The additional layer of frontend complexity made it even harder for new hires to be productive from day one.

When we first saw this project on the horizon, we realized it would end up requiring a substantial refactor of our web app. We had a few options:

  1. Rewrite the JavaScript in a way that makes it simpler and easier to use.
  2. Don’t rewrite JavaScript.

We went with option 2.

Instead of using a client side MVC framework to help enable us to write a single page app, we opted to use our Rails server to render views, and we used server generated JavaScript responses to make the app feel just as snappy for our customers. We achieved the same UX wins as a single page app with a fraction of the code.

Method to the Madness

The crux of our new pattern is this: We use Rails’ unobtrusive JavaScript (ujs) library to declare that forms and links should be submitted using AJAX. Our server then gets an AJAX rest request as usual, but instead of rendering the data as JSON, it responds to the request with a snippet of JavaScript. That JavaScript gets evaluated by the browser. The “trick” here is that JavaScript is a simple call to jQuery’s html method, and we use Rails’ built-in partial view rendering to respond with all the HTML we need.

Now, the frontend just needs to blindly listen to the server, and render the HTML as instructed.

An Example

As a simple example, let’s say we want to edit a user’s home address. Using the JavaScript single page app framework, we would need a few things.

First, we want an address model, which we map to our “/addresses” endpoint.

Next, we need a View, that represents our form for editing the address.

We need a frontend template for that view.

Then, we need a route in our frontend for navigating to this page.

And for our server, we need to add a route, a controller, a model, and a jbuilder to render that model as JSON.

A Better Way

With our new paradigm, we can skip most of this. All we need is the server. We still have our route, controller, and model, but instead of a jbuilder for returning JSON, we can port our template to embedded Ruby, and let the server do all the work. Using UJS patterns, our view can live completely on the server.

There are a few major wins here:

  1. Unifying our business logic.
    The server is responsible for knowing about (1) our data, (2) how to wrap that data into rich domain models that own our business logic, (3) how to render those models into views, and (4) how to render those views on the page. The client needs to know almost nothing.
  2. Less JavaScript.
    We aren’t getting rid of all the JavaScript in our application. Certain snappy user experience elements don’t work as well without JavaScript. Interactive elements, some delightful animations, and other frontend behaviors still need it. For these things, we are using HTML data elements to specify behaviors.

    For example, we can tag an element with a data-behavior-dropdown, and then we have some simple, well organized global JavaScript that knows how to wrap that element in some code that makes it more interactive. We are hoping that by using these patterns, we can limit our use of JavaScript to only know about how to enhance HTML, not how to automatically calculate net income when trying to distribute excess tax year contributions from an IRA (something that our frontend JavaScript used to know how to do).

  3. We can do this migration in small pieces.
    Even with this plan, migrating a highly complex web application isn’t easy. We decided to tackle it using a tab-by-tab approach. We’ve written a few useful helpers that allow us to easily plug in our new server-driven style into our existing Marionette application. By doing this piecemeal, we are hoping to bake in useful patterns early on, which we can iterate and use to make migrating the next part even simpler.

If we do this right, we will be able to swap everything to a normal Rails app with minimal effort.

Once we migrate to Rails 5, we should even be able to easily take advantage of Turbolinks 3, which is a conventionalized way to do regional AJAX updates.

This new pattern will make building out newer and even more sophisticated features easier, so we can focus on encapsulating the business logic once.

Onboarding new hires familiar with the Rails framework will be faster, and those who aren’t familiar can find great external (and internal) resources to learn it. We think that our Web app will be just as pleasant to use, and we can more quickly enhance and build new features going forward.

More from Betterment: 

Recommended Content

View All Resources
The Difference Between Vanguard and Betterment

The Difference Between Vanguard and Betterment

I’ve been asked a lot in the last few months in the transition from my old role at Vanguard to my new role as Chief Growth Officer at Betterment – what’s the difference between the two companies?

How to Do a Direct IRA Transfer

How to Do a Direct IRA Transfer

If this is your first direct IRA transfer, don’t worry. We help process direct IRA transfers every day, and we’re here to make it as easy for you as possible.

Get All the Returns You Deserve

Get All the Returns You Deserve

We set out to make investing more efficient—and we have. With our platform, your investor returns can get a boost of 2.66%.

Explore your first goal

Safety Net

This is a great place to start—an emergency fund for life's unplanned hiccups. A safety net is a conservative portfolio.

Retirement

Whether it's a long way off or just around the corner, we'll help you save for the retirement you deserve.

General Investing

If you want to invest and build wealth over time, then this is the goal for you. This is an excellent goal type for unknown future needs or money you plan to pass to future generations.

Smart Saver

You could earn 20X more than a typical savings account with our low-risk investing account for your extra cash.

How would you like to get started?

Your first step toward a smarter investing future starts here.

Create a Betterment account

Go ahead and join the smart, modern way to invest.

See what we can do for you

Tell us a bit about yourself, and we'll show you the benefits of investing with us.

Get a free investing checkup

Help us get a sense of your investing approach and see how you could improve.

Transfer a 401(k) or an IRA

Move an existing retirement account into a Betterment IRA.

Download the mobile app

Enjoy the Betterment experience anywhere on the go.

<title>Close</title>

Search our site

For more information and disclosures about the Betterment Resource Center, click here. | See our contributors.