Web Development

Universal JavaScript In The Wild

Earlier this month, Netflix announced that they had dropped Java from the rendering pipeline for their primary netflix.com web application. In its place, the company is using an architecture that leans on two technologies that have received an immense amount of press in the last couple of years - Node.js and React.

The fact that Netflix is using either one of these tools to power its most public and widely-accessible app would be newsworthy on its own, if perhaps a bit unsurprising to engineers building modern applications for the web. (Node.js is being used in production by PayPal, LinkedIn, Microsoft, and many others. React, originally created at Facebook, is a major part of that company’s front-end architecture and is gaining traction at many other companies, including the BBC, Dropbox, and Airbnb.)

What’s exciting to the web apps team at WillowTree is that Netflix has chosen to use these two tools in conjunction to build a “Universal JavaScript” application. This application pattern - which has also been called “Isomorphic JavaScript” - can improve user experience and make code more reusable and easier to maintain. WillowTree is using React in most of our new projects, and version 2 of RentalSpot, an internally built product we’re rebuilding from the ground-up, uses the Universal JavaScript pattern.

Universal JavaScript isn’t a silver bullet, but for apps where it makes sense, the pattern offers some compelling benefits over other web architectures. To understand how Universal JavaScript works, we should identify two other kinds of architectures common on the web, as Universal apps occupy a kind of middle ground between them.

HTML From The Server

This is the way the world wide web was originally conceived. The user makes a request to a server via a web browser. The server responds to the request with an HTML document. Done.

Well, not really “done.” Ever since Microsoft invented Ajax in the late 90s - and Google made it famous by releasing Gmail in 2004 - web pages have been using JavaScript to make requests for new data from the server and updating that initial HTML page in real time based on user interaction. But in an HTML-from-the-server world, major changes to the page - say, going from “Home” to “News” - is going to kick off a page refresh and an entirely new and complete HTML document from the server.

But here’s the most important point: the majority of the view and UI logic -that is, how the page looks and functions - is computed on the server. Most commonly, an completely different programming language is used on the server to generate that page - Ruby, PHP, Python, etc. JavaScript is used in the browser, so some duplication of UI logic is almost inevitable.

Over the years, various tools have popped up that try to reduce this redundancy. Mustache, a templating language that allows users to layout HTML in a language-agnostic way, remains a popular option. But it requires some capitulations on the part of developers - most importantly, it’s intended to be used for presentation, not for application logic.

Additionally (and also very important): complex and highly-interactive UIs become much more difficult to build and maintain.

JSON (or some other structured data) From The Server

In the other direction, the primary source of UI and presentation logic may be done in the browser via JavaScript. This is frequently referred to as a Single Page App (SPA) architecture. In most cases, a very basic HTML page is sent to the browser. That HTML typically sets up a basic UI shell, which is then filled asynchronously by client-side code. Next, a sometimes lengthy and complex series of Ajax calls back to the server loads the app with data, and the app uses that data to build the UI.

In many cases, no HTML is sent to the browser from the server after that initial page load. The result is a UX that’s more responsive and "app like.” Complex UI interactions - especially when you’re dealing with long-running sessions - become much easier to reason about and build.

This is how WillowTree builds most of our web applications. Because we’re so comfortable with this architecture, we’re also intimately familiar with two of its biggest drawbacks:

  1. Performance of direct links. You’ll see this weakness trotted out pretty often when folks bemoan performance of the mobile web. The argument typically starts something like, “Why do I need 3 MB of JavaScript just to read one blog post?” It’s a fair criticism. When all of your UI is generated by JS, it takes a lot of that code to generate a single, quickly-abandoned page. For users hitting your app from a direct link on Facebook, there’s often too much application code to download. There are a number of different ways to mitigate this problem, but they all add some level of programming complexity.

  2. Search Engine Optimization. Google is getting better at indexing JavaScript heavy web sites, but we’re still living in a world where search engine bots, from a technical point of view, act like browsers from 2003. WillowTree uses a server side solution that pre-renders pages for search-engine bots. It works extraordinarily well for indexing, but…well, honestly, it just feels janky.

Universal JavaScript

Back to Netflix. They and the RentalSpot team at WillowTree are attempting to architect a “best of both worlds” solution.

Node.js is the most important part of the equation here. Because Node allows you to execute JavaScript outside of the browser, tools like React are able to provide hooks for running the same code in either the browser or on the server. Here’s what happens when a user loads a Universal JS app in their browser.

blog-post-image react-graphic MD

This is a bit oversimplified, but it captures the essence of what makes this architecture unique. In sequence:

  1. The user makes an initial request to your site.

  2. The server receives the request and uses the React application code to gather data and assemble views. The end result is a string of HTML.

  3. The server responds to the request by delivering that HTML to the browser. This is why Universal apps are so good for SEO: this is HTML that any search engine bot can understand. No JavaScript has yet executed on the browser. However, as part of this response, the server has also sent down the same view code used on the server to the browser.

  4. The user interacts with the page. For instance, they might click some main navigation from your home page to the “events” section of your app.

  5. The React app residing in the browser handles updating the associated views.

Steps 4 and 5 are repeated until the user refreshes the page or requests a page that specifies a full HTML refresh from the server should occur.

This has a real UX impact. Instead of the spinner or splash image commonly shown as JavaScript loads in single page apps, the user is presented with a fully rendered view on first page load. This does assume that your server side code is optimized for this task. But generally speaking, it is easier to optimize server side code for performance than optimizing client side where browser environments are out of your control and system resources are more constrained.

To Reiterate: There’s No Silver Bullet

Programming for the web has always been about trade-offs. For Netflix, where initial page load speeds are critical and their dev team - back and frontend developers - are comfortable with and productive in the new environment, it’s likely a great (dare I say “the perfect”?) decision. However, it’s important to consider that Universal JavaScript is a new technology. As a result, there’s a good deal of churn around the “right way” to approach technical design. For example, our team has had a number of discussions about the best way to marry routing (that is, determining the proper page to display) and data fetching.

As the patterns firm up and the tools around Universal JS continue to improve, expect to hear more sites adopting the architecture. It’s a compelling option with real benefits for users and developers. In the software development world, it’s hard to ask for more than that.

Being Proactive in Security: The Case of the SolarWinds Breach

With the recent news of the SolarWinds security breach circulating the Internet...

Read the article