Universal Javascript in Production - The Why
This is a transcript of a talk I co-presented for Intuit's Front-end Engineering Conference. This is part one of a two part post on Universal Javascript in Production.
Context setting
At Intuit, I am a full stack engineer on a product called QuickBooks Financing, which is a platform that provides financing options to eligible small businesses. We initially launched our first product in February of 2013, so for those of you can’t math, this is just a little under 3.5 years ago from this time of writing. Our very first product was a web application that was simply a match-making platform that is very similar to Kayak, but with loans instead of plane tickets. Since 2013, we have had many iterations of our product; we have been able to refine our customer problem and we are growing our business to reach any small business within all of our product lines. This includes both our QuickBooks Desktop and QuickBooks Online users.
So how was this built? Well, in the early days, the founding engineers on the team had built our first product under the .NET stack. For what we needed to do at the time, .NET was a great platform! It had given us a full software framework that provided everything that we needed from its pure MVC web framework to its mature services architecture. However, QuickBooks Financing has grown dramatically over the years, and the .NET environment didn’t quite grow or mold itself well into Intuit’s technology ecosystem. Our product has always been a services oriented, single page application experience. As a result, the .NET MVC framework provided us no real benefit for our presentation layer. Not only that, with Intuit's AWS journey, being able to reuse the same Java code as our sister start-up, QuickBooks Self-Employed, and integration with the QuickBooks Online plugin architecture were all additional hurdles we needed to eventually address. Given the growth of our business and the new initiatives we have in place, we had reached a point where we were not able to scale.
So what would most engineers do in our situation?
Rewrite everything of course! That’s right, we rewrote the whole damn platform, and we did it in a little over 4 months with seven engineers.
Planning the rewrite
Intuit has always been a Java house. There are several teams that like to go rogue and build their products under different technologies (e.g. like we did). This wouldn't be a problem if every integration or feature was implemented as an API or service. Intuit is on a journey of everything-as-a-service, but we're not quite there yet. There are still some SDK's and integrations that are only compatible with Java. So as part of the rewrite, the team had collectively decided that for our backend API layer, it should be written in Java. So where does that leave our presentation layer?
For the most part, QuickBooks Financing is a single page application (SPA), so a lot of the work is front-loaded onto the browser. Both the existing Java web frameworks and .NET are very good at handling server-side generated pages. But because we're a SPA, most of the responsibilities of our web server were to simply make sure all of the assets were properly provided to the browser.
Whilst working in the .NET worldm we were running into many issues when building new UI features. These included issues where we needed to manage and load the proper UI experience when we run many AB tests, compiling and bundling the right assets on every build, keeping up with all the copy and UI changes for every single one of our experiences, improving initial page load, and preventing duplication of work. Any new UI feature was a pain in the ass to develop and test. I still have painful scars of how we used to operate.
At its core, these issues could summarized into the following:
- Our developer productivity was hurting
- Modern web design practices had outpaced our current stack, which affected our user experience
If we stayed within the Java landscape in its entirety, we would have run into the same issues as our .NET infrastructure.
Node.js to the rescue!
So to remedy these problems, we arrive at Node.js. This magical runtime that enables us to write our backend in Javascript. As you know, everyone and their mom loves Node. Everyone and their mom loves Node. To many, Node is the best thing to happen since bacon and pancakes!
But whenever you ask someone why they love Node, they will always say, “because you know... event-driven, non-blocking IO!” But let’s be honest for a second, how many of you are actually actually using it for that?
For us, Node’s biggest strengths lie in NPM and Universal Javascript.
Because Javascript does not really contain the concept of a "core library", NPM gives us the ability to easily grab code that enables us to build a modern web experience quickly. Universal Javascript allows us to improve productivity by allowing us to write the same code for both the client and server, removing any duplication.
Universal Javascript
And that finally brings us to Universal Javascript. If you don’t already know what Universal Javascript is or if you didn’t already gather it from the context clues, Universal Javascript is the ability to write the same Javascript code to run on both the server and the browser. But wait! Isn’t that Isomorphic Javascript? Yes, they are the same. Universal Javascript is the new hip, politically correct name for it, because people finally realized that the word isomorphic makes no goddamn sense in this context.
So why is Universal Javascript a good thing? I don't want to rehash what's already been written out there, so I will direct you to a great example from Netfli. You can read more about their journey here. With this rewrite, we are effectively leveraging the same benefits and implementing the same features as detailed in Netflix's blog post.
Now that I've sort of gone over why we're using Node.js and Netflix has already done a great job explaining the benefits of Universal Javascript, how did we implement it in QuickBooks Financing? This is discussed in part two. In part two, we do a deep dive and go over in detail how we were able to improve our user experience through Universal Javascript.