Single Page Application Done Right

* The post was also featured @

Single Page What?!

Not too long ago, moved its website from classic web architecture (CWA) to a single-page application (SPA). For those who are less familiar with SPA, the major differences between the two are as follows:

  1. First client request:
    • CWA: The server returns a full HTML page
    • SPA: The server returns a set of templates and data which is then rendered to the full HTML page, by Javascript, on the client side.
  2. Subsequent requests
    • CWA: The server returns a full HTML page
    • SPA: The server returns only the data needed to display the request. Since all templates are already on the client side from the first request, no HTML/CSS/JS should be delivered.

To put it in simpler words – while in CWA the client gets a full HTML page on each request, in SPA the client gets all needed to be able to render the HTML by itself on the first page load so that subsequent requests might be carried in a very fluent and rich manner. It makes your website more of an application and less of a site.

Pros & Cons

SPA heavily relies on Javascript to perform actions that were server only a few years ago. It means that a large part of the “heavy lifting” involved in creating web pages is now the responsibility of the client, for better and for worse. Let’s go over of the advantages and disadvantages of SPA over CWA. Advantages:

  • User experience is much richer and fluent.
  • Lower server load: Because HTML rendering is done on the client and subsequent requests only require the specific data needed to render that page.
  • Definitive separation between client and server – server acts more like an API.


  • SEO: Search engines (Google etc…) do not execute Javascript when they index your site. Since in SPA pages are rendered on the client side by Javascript you need to find a way and supply search engines with a full HTML page.
  • Caching: Since pages are rendered on the client side, you can’t cache full HTML pages on the server end. This also impacts CDN services as what they will cache will be only templates and not full pages.
  • Performance: As said, SPA is heavily client-side dependent. It means that your site might load fast on some clients while being painfully slow on other. This becomes a large factor as old mobile devices might have a rough time rendering the pages and introduce large load times for your site.

No Compromises

We knew that we must build our web site as a SPA in order to stay relevant and provide our users with the best possible experience. We also knew we will have to overcome those disadvantages if we wanted to be able to keep our SEO rank high and our users happy. There are several solutions to these problems like PreRender but they are more focused around SEO solutions and less of the other two. We wanted a solution that would enable us:

  1. Be indexed by Google bots and other search engine crawlers.
  2. Cache full pages HTML on the CDN and on our server cache.
  3. Improve user experience on old mobile devices’  which were suffering from the heavy Javascript execution a normal SPA requires.

We figured out that what we really need is a hybrid between CWA and SPA: We want to return fully rendered HTML pages on the first request while subsequent requests behave just like normal SPA. If we could achieve that target, we will enjoy all the advantages of SPA with all the disadvantages eliminated since:

  1. Google bots and other crawlers will easily index our pages since the server returns fully rendered HTML pages.
  2. There is no problem to cache full HTML pages on the server and the CDN will also have a full HTML page cached.
  3. Since we render HTML pages on the server no additional work is needed on the client side (at least for the first request) for the page to be shown. This decreases the dependency on client hardware which mainly impacts old mobile devices.

Since there was no product or service fulfilling all three, we set out on a journey to create one ourselves. The idea was to use PhantomJS,  which is a headless browser capable of running Javascript, to render our SPA pages. The journey ended with 3 separate open source projects: phantom_renderer, phantom_manager and phantom_server. Each has its own important role in the process of producing a full HTML page for our client.

How Does It Work?

FTBpro PhantomJS architecture
FTBpro PhantomJS architecture
  1. Client (user) requests a URL – assume it is /posts/3 from the web server
  2. The web server, via phantom_renderer asks phantom_server to render /posts/3
  3. phantom_server requests SPA version of /posts/3 from the web server
  4. The web server returns the SPA version to phantom_server
  5. phantom_server renderes the SPA to a full HTML page
  6. phantom_server returns a full HTML page to the web server
  7. The web server returns a full HTML page to the client

Let’s talk a little bit about each of the components and what are their roles in the system.


phantom_renderer is a ruby gem which integrates with rails controllers and communicates with the phantom_server in order to produce a full HTML page. It is responsible on two important things:

  1. Caching: when full HTML pages are returned by phantom_server they are being cached so that they won’t have to be produced again.
  2. Managing phantom_server responses: In case of bad (5xx) response from phantom_server a regular SPA page will be returned to the client. The same is applied if phantom_server does not respond in a given timeframe (configurable). This way, even if something bad happens to phantom_server we fallback to a regular SPA.


At the beginning we were having a lot of problems with PhantomJS processes over time: Some of their memory got bloated, some of them crashed and some of them just stopped responding. We had to come up with a solution to make those processes more stable or at least monitor them somehow. phantom_manager does just that: It manages a predefined amount of PhantomJS processes behind an NginX server. For example, when one PhantomJS process stops responding it will remove it from the Nginx Configuration and re-add it only after it raised another process instead. This way we keep a constant pool of PhantomJS processes which are always ready to render a page.


phantom_server is a collection of technologies making the whole rendering process happen. This is how it works:

  1. An NginX server listening to port 80
  2. phantom_manager manages PhantomJS processes on ports 80xx. It syncs every action it does on PhantomJS processes with the NginX Config.
  3. Each PhantomJS process runs a customized version of
  4. Requests are delegated from NginX directly to PhantomJS processes on ports 80xx


The system has been up and running for about half a year now. It is all open-source and ready to deploy. If you have a SPA site, and experience the same issues as we did, give it a try. We will be more than happy to help with any setup issue you encounter.

One thought on “Single Page Application Done Right

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s