The Internet in its early stage looked pretty rough. That period could be called the Middle Ages of web development. Nobody knew what the ‘User Experience’ term meant in the context of websites. Content was organized equally well as stains on abstract images, links had to appear in their underlined form and animated GIFs were everywhere. How cool was that!?
Some time later, the PHP language has appeared. Websites were enriched with dynamic content. Webmasters (one of the most distinctive words of that ancient glossary) were enabled to use a bunch of Content Management Systems (like WordPress, Joomla) or even to craft their own ones. New websites started to pop up like mushrooms. Everyone could note their online presence, by having their own website. A revolution had started. Even now, we can easily find traces of that process. According to W3Tech, PHP is used in 82.2%, and WordPress in 28.5% of all websites!
Golden train on Rails
About 10 years later, the Rails framework saw the daylight. It vastly popularized the Ruby language and became a strong advocate of the Model-View-Controller pattern. But first of all, it enabled developers to quickly deliver relatively advanced features to their clients. It was famous for its ability to create custom blog engines in 15 minutes (try to google “rails 15 minute blog”). Websites were getting more and more sophisticated.
Almost every modern web application makes a clear distinction between the client and the server. Clients focus on presenting data and handling user interaction. Core business processes are handled at the server side, where we have the opportunity to authorize and validate user intents. It is also common to move CPU or memory heavy computations to our backends.
Did you realize that I wrote ‘web application?’ They are not ordinary websites or webpages anymore. Of course, you can call Google Docs a website only, but from a technical point of view, that would be an oversimplification. Websites which do not require a full page refresh after the initial load are called Single Page Applications. Fetching additional data and redrawing it in the user screen is performed at the client’s browser. That results in a native-like experience. Using that kind of app is very similar to using desktop or mobile counterparts. They are often enriched with animations, performing the actions has an immediate reflection in the UI and navigation through them is very smooth. And in addition, they can keep all the advantages of traditional websites (e.g. sharing content via deep link). Those types of apps have become very popular these days. There are many frameworks and libraries which simplify bootstraping this modern pattern – like Ember.js, React, AngularJS, among others.
Single Page Apps have several advantages:
- Untie UI from request/response cycle
In a traditional server-rendered website, resource retrieval is constrained to fetching a whole HTML document. Even if only a small part of the layout has been changed, the server is obligated to generate a whole document as a response. That attitude is very simple and has worked well for years. But the constantly growing expectations and requirements faced by today’s web-apps make it too limiting. More and more data is fetched asynchronously, after the initial render of the website has been done. That allows web-apps to better fit user intents and results in a more flexible and eye-catching UI.
- Strong separation of concerns
Each part of the system is only responsible for its own duties. The backend should not be aware of the UI & UX details. In turn, frontend does not necessarily need to know about the database engine used to store data and its denormalization. That leads to a more decoupled architecture, which is more change-resilient. And that reduces the cost of maintaining the code and introducing new features.
- Flexibility of deployment
As we have two independent applications instead of one, we can deploy them separately. Each of them needs to meet different conditions. For instance, our backend may serve as an API for a web app, Android and iOS apps. It may even expose some part publicly, in order to enable other applications to integrate with it. All those sources can generate vast amounts of traffic. Such requirements imply using a powerful machine or applying some cloud solutions. On the other hand, a server which only pre-renders a Single Page Application does not need to be that capable.
- Flexibility of development
- Reduction of bandwidth
Single Page Apps do not need to fetch a whole HTML document from the server. They contain all graphical components, styles and know the HTML structure. Data is only one “moving” part, and transferring it in a JSON form is noticeably more lightweight. That matters, especially on mobile web.
The dark side of the Moon
The programmer split up his app and saw everything that he had made, and, behold, it was very good. Well… almost everything. Life is not that easy and the IT world is not a bed of roses. It is all about trade-offs.
If you decide to split up your system into a separate backend and frontend, you can stumble across several obstacles:
- Time to market is longer
Since we are dealing with two subparts, each with a separate codebase, starting with a simple prototype would be a bit more time consuming. Bootstrapping a new project has some initial cost, and now we have 2 projects, not one! This slowdown is particularly visible in small apps based mostly on forms. SPA in such cases may be an overkill.
- Communication overhead
- Need for a clear contract between the frontend and the backend
Communication comes at a cost but should have clear boundaries, too. Data flow between the frontend and the backend is like dialogue. And what’s the necessary condition of a successful conversation? Mutual understanding. Interlocutors need to speak the same language. To make it possible, they need to state the rules and undertake to follow them. Some kind of contract needs to be established. In IT, this is usually called an API (Application Programming Interface). Documenting an API and keeping this documentation up-to-date is a cost.
There are solutions which enable API documentation to be generated directly from the code. That results in an always-up-to-date description of the contract, and eliminates the manual labour involved in developing and maintaining the documentation. One of them is GraphQL accompanied by GraphiQL. This mix delivers a dynamic, interactive and solid way of exploring API from the first day of project development. Actually, it is not possible to create a backend which uses GraphQL without documentation.
- Initial load
As I wrote (in the “Schism” paragraph), Single Page Apps are responsible for drawing content in the user’s browser. This is generally a good thing, but also has a side effect. In order to render anything, client browser must load and interpret application code. This could take a while, especially for large apps. Until then, the user does not see any meaningful content beyond a kind request to wait paired with some loader (a white page in the worst case).
- Availability for web crawlers
A longer initial load is a bad thing, but it can be even worse. Imagine that you have written some fancy blogpost or cooked a delicious meal and you want to let your friends know about the recipe. You have taken beautiful photos and written a decent description. Your content is available at http://fancy-spa.com/polish-dumplings, so you just pick an URL and share it on Facebook. And guess what happens? Facebook displayed no photos, no title and no description at all. On your wall, there is just a solitary link to your lovely dumplings, which looks broken nonetheless. No-one will click on it. You plunge into sorrow.
Why does it have to be like that? The Facebook robot visited the URL and got a blank page at the very first moment, just like you did. But it was not patient or smart enough to wait for the actual content to appear. It falsely assumed that the page was blank. Allowing web crawlers to correctly fetch data from your website is often a crucial factor in your business success. As we all live in the era of social networks, it would be foolish to not use that medium to our advantage. Shareable content helps your app to grow for free.
In Appchance, we overcame this constraint. When we were choosing the frontend framework, support for server pre-rendering was on the top of our priority list. We chose Ember.js, which has this feature practically built-in, thanks to the fantastic ember-fastboot addon. So we can have all the benefits listed above with minimized drawbacks.
Single-page applications have become a standard in the web industry. They offer an experience comparable to desktop or mobile apps, with all the advantages of traditional websites. They are the natural choice, when providing smooth and snappy interaction is essential. And you can be sure: your users will fall in love with your product. It is also worth noting that SPA is only one step away from PWA (Progressive Web Apps. Yeah I know, another 3-letter acronym, IT loves them), but that is a topic for another blogpost.
In spite of their undeniable superiority, adopting SPA should be a conscious decision, not a result of herd instinct. The additional complexity they introduce needs to be handled somehow.
I hope this blogpost has enabled you to thoroughly explore the world of modern web applications. A better understanding of the rules of that world could be beneficial for your next product. And maybe you already have some experience with SPA?