Why You’ll Always Need Isomorphic JavaScript

Max Jung
6 min readJul 8, 2016

--

Isomorphic apps originally gained popularity because of the ability to provide the benefits of client rendering while also using server rendering to maintain the ability to have proper search engine indexing — a problem that all client rendering applications faced. Isomorphism was the best of both worlds, but there was a decrease in enthusiasm around it after Google announced their support of JavaScript based rendering. It was as if Google addressed the problem of client rendering application not being indexed properly, and the need for isomorphic apps disappeared. However, the need for isomorphic applications is still evident, since the problem of SEO isn’t fully solved, and the added performance and user experience improvements that this type of application rendering enables. This article will review isomorphism’s relevance for the modern web, and support the claims with benchmark tests and data.

More on Isomorphic Apps

On the spectrum of client rendering to server rendering, isomorphism sits in the middle between the two. It means “of similar composition,” and takes it name from the fact that the client and server share a similar codebase.

In primarily single page applications using libraries like Angular or React, the server does minimal work and sends a basic HTML document, while the client code does the heavy lifting and renders the entire user interface, as well as managing all user interactions and updates. Any external data will be populated with AJAX requests. While this approach enables realtime feedback to user interactions, it can’t show meaningful information initially until it gets enough external data.

On the opposing end, websites using server rendering technology, commonly written with frameworks like Ruby on Rails or Django, have most of the rendering work done on the server. Some user interactions still happen on the client, but they are minimal, since large updates will require another round trip to the server to re-render the entire page. This approach provides a better initial content but requires expensive network transactions for updating user interfaces.

Isomorphism gives you the benefit of both worlds by providing prepopulated initial page and autonomous client rendering for further user interactions.

Key Benefits of Isomorphism

Better user experience

By rendering important parts of the application with the real data on the server side, an isomorphic application can show a meaningful initial page. On the other hand, client rendering application can’t show any meaningful information until it fetches all external data it needs. In the meantime, only thing a user will see is a loading indicator.

Faster overall loading time

Although an isomorphic application will be slower in responding an intial page compared to a client rendering application (as it fetches data and renders more markups on the server side before responding), overall completion time to the final user interrace is faster because data access on the server side is much faster than client side API requests.

More predictable SEO and Site Indexing

In order to index content that JavaScript apps render on client-side, Googlebot must run those JavaScript apps inside a full browser environment and capture the rendered DOM. This involves complex browser compatibility issues. Also, because JavaScript apps can make AJAX requests for further rendering, Googlebot must have a policy that controls apps’ network access. These are why getting your JavaScript app indexed properly by Googlebot is still challenging.

The following two images demonstrate the issues in more detail.

In this image, we use Google’s webmaster tool called “Fetch as Google.” It shows you how your app will be seen by Googlebot. As you can see, our benchmark app’s client-only rendering page is rendered correctly using this tool.

But here, we can see that the cached version of our site does not display properly. It’s very likely that the API request made inside the application to populate the content was blocked in the real Googlebot.

In addition to this, we observed that the Googlebot doesn’t have built-in promise support. So if your app uses a promise without a polyfill backup, it will crash inside the Googlebot and become unsearchable.

Benchmark Details

In this benchmark, the overall loading speed of an isomorphic rendered page is compared to that of a client rendered one. In the client rendering example, there is a 200ms delay on the AJAX response from the API server in order to simulate a real-life database access. Once the response is received by the client, content markups are rendered from the data. The server sends a basic HTML document without any data or content markup.

For the isomorphic rendering example, the server fetches the data, also with a 200ms delay, and then sends the HTML with the data and pre-rendered markup.

The benchmark was run with 5 trials per AWS availability region, and run over 3 availability regions to take into account different server distances from the client. The 3 regions were N. California, N. Virginia, and Seoul. There were also two separate benchmark comparisons run, one is with an initial render, and the second benchmark is with assets from the browser cache.

Here are the results from the N. California benchmark:

N. California — Not cached

N. California — Cached

See the full, detailed benchmark result data here

For the results, an isomorphic rendering saw an average improvement of 21.5% in loading speed over the client rendering, and when cached, the isomorphic rendering was 42.4% faster than the client rendering.

Conclusions

Isomorphic rendering must be carefully designed and balanced. It’s more nuanced than a binary decision process, since a page can have different area of server rendering and client rendering combined.

Server rendering is important for the part of the page that is critical to user’s perception as having a “loaded” state, such as the body text of a blog post or the profile parts of a news feed.

Client rendering should be used for the part that that can be delayed without impacting user experience, such as the comments of a blog post. It’s also good for the part that can be rendered on demand, such as a ‘Read More’ button. Using server rendering for these parts would only delay the initial response time without much benefit.

Take for example any of the popular web applications in use today, Facebook, Instagram, or Twitter. If you notice, these applications have a very large amount of data that needs to be populated onto your profile and news feed. To circumvent the problem of displaying a blank screen or loading indicator while it fetches data, these applications render the initial layout of your dashboard, such as the structure of your news feed and some basic profile data, before then populating your news feed and notifications.

By finding a balance between client and server rendering for your isomorphic application, you will optimize performance, maximize user experience, and ensure predictable searchability.

Check out the benchmark code here

--

--