architecting a web application: the single-page application

May 20, 2020

It's sleek. It's new. It's a single-page web application. Let's talk about it!

What is a single-page application?

A Single-page application (aka SPA) is a type of web app where the webpage itself never reloads. If this sounds a little bit confusing, that's ok! To explain what I mean, let's take a small step back and talk about how the internet works.

Let's talk about the internet.

At its core, the internet is just a bunch of computers connected together with really long cables. Of course, it's much more complicated than that, but it's a pretty good mental model! Using that model, someone opens up their web browser of choice and types a URL into the bar at the top of the screen, they are giving the browser instructions about where to find the desired information. When you navigate to that URL, your computer reaches out to another computer and engages in a short conversation that goes something like this:

"Hey there." - your computer

"Oh hello." - the other computer

"Have a second?" - your computer

"Yep. I've got time." - the other computer

"Ok, can I have whatever data you know about for google.com?" - your computer

"Oh, sure. Here you go." - the other computer

"Ok great, thanks. Nice talking to you." - your computer

"Sure thing. Have fun storming the castle." - the other computer

During this conversation, your computer and the other computer (commonly called a "server") are exchanging all sorts of data back and forth. For our discussion about web applications, the essential data that comes back from the server is HTML, CSS, and JavaScript files. These front-end files are what render in your computer's web browser so that you can see the web app.

Traditionally, whenever your computer initiated a conversation with a server, it would receive those same sorts of front-end files as a result. This is how monolithic applications (check out the previous article in this series for more information) have worked for years. Recently, however, single-page applications have added another option for developers looking to make web apps that feel more like native applications.

So let's talk about SPAs.

SPAs are vastly different from their monolithic, server-rendered counterparts because the only time that they will receive front-end files from the server is on the initial page load. From then on, no more HTML, CSS, or JavaScript files are being sent back and forth during your computer's conversation with the server.

So how then, does a single-page application DO anything?

Instead of requesting entire pages from a server, a single-page application is specifically built to retrieve small bits of data from a server and use that new information to re-render specific parts of the app without having to reload the entire page.

Let's take the example of a user attempting to navigate to another page. In a server-rendered application, the entire page would reload and render the new page in the browser when the user clicks or taps on another navigation item to change the page. However, in a single-page app, when a user clicks or taps on a new navigation item, the SPA sends out a request to a server for ONLY the data required for that new page. When the SPA gets that data back, instead of completely reloading the page, it will re-render the specific parts of the app that need to change based on the new data. This means that much of the application will remain unchanged on-screen, and there will have been no page reload!

Building a Single-Page Application

At the time of writing, there are a few prevalent JavaScript frameworks that developers are using to build SPAs. Any of these will work to create an SPA, mostly it just comes down to which of them you prefer. I'll also say right up front that these, by no means, are the only ways to build single-page apps; there are plenty of other frameworks that you can use, but these are the most popular at the current moment.

Pros of SPAs

Easy scalability & low hosting costs.

One of the primary benefits of SPAs is simple scalability. When hosting a web app, it's common for people to spin up a virtual server with a cloud hosting provider, install all of the server software, and host their application. While this is certainly an acceptable solution, we can do better.

One service offered by most cloud hosting providers is the ability to host "static sites" from their low-cost object storage solutions. These solutions (such as S3 in the AWS Cloud) have an incredible track record of uptime and speed due to their distributed nature. We'll go more in-depth on these solutions in another post, but essentially, developers can leverage this distributed S3 system to host their app all across the globe for an insanely low cost that will scale practically infinitely.

It feels like a native app.

Native apps have quickly grown in popularity in recent years, and now an argument could be made that users of web applications expect the same performance levels as the native apps they know and love. SPAs have a knack for delivering a crisp, snappy experience once the app has loaded onto the user's browser. Since the page doesn't have to reload on every request, everything just feels a little better and more cohesive than most server-rendered apps.

Native app development becomes easier.

Speaking of native apps, building an SPA can make creating native applications easier in the long run. Since SPAs aren't housed in the same codebase as their corresponding back-end logic, they have to make use of AJAX calls to an API to make use of any real functionality. Native mobile applications work in much the same way, making use of external APIs to interface with services over a network. That means that you can use a vast majority (if not all) of your API code in both places, leading to a more cohesive environment overall.

Cons of SPAs

Things start to get complicated fast.

In order to build the smooth, crisp experience that users are expecting from SPAs, there are a lot of complex problems that need to be solved behind the scenes. In reality, there are great tools that will assist developers with these specific issues, but it doesn't mean that these problems aren't still complicated and difficult to execute if a developer doesn't know what they're doing.

  • User authentication needs to be handled very carefully, because, as mentioned in the article on the "almighty monolith," SPA authentication techniques like JWTs still need to be implemented correctly, unlike their session authentication counterpart that is already implemented in every browser.
  • State management on the front-end can get a bit tricky. In a server-rendered application, your database is your single source of truth--the data in the database informs your state. With SPAs, developers have to manage and reconcile two separate data sources: the remote database and their local state management system.
  • Front-end routing is a glorified hack. There. I said it. Don't get me wrong, I think that the libraries and techniques used to make front-end routing work are doing a fantastic job, but server-side rendering is just so much simpler and more robust at the moment.

SEO optimization is (maybe) impossible.

This isn't as truthful as it used to be, but in general, it is harder for web crawlers from the major search engines to index a website that is built as an SPA. Google has said that their web crawler can now crawl SPAs with "high fidelity," but if you need 100% sure-fire SEO optimization, you're better off avoiding SPAs.

JavaScript is visible to end-users.

JavaScript, the language that powers SPAs, is not a compiled language. That means that, at any time, a user can pop open their console and see an SPA's underlying codebase. Good ways of obfuscating code exist (like minification and uglification), but if a user can SEE the code, a user can BREAK the code. Thankfully, most seasoned developers will make sure that no secret credentials or environment variables make their way into the front-end code, but there's always the chance of that happening!

TL;DR

SPAs are fantastic ways to build web apps that feel like native apps. They're snappy, very user-friendly, and incredibly scalable for cheap. There are tons of fantastic JavaScript frameworks that you can use to help smooth out some of the rough edges of building an SPA, letting you spend more time ironing out the business logic of your next big idea.

It's important to note that SPAs aren't a golden hammer--there are many situations where they fall short. They can become incredibly complex and insecure if done incorrectly and can be hard to debug.

If this all seems a little overwhelming for you or for your app idea, don't fret! One of the most critical parts of architecting an app is that, at some point, it doesn't really matter what you use to build it. As long as you can get your product to market and into the hands of users, you can always optimize and change things later on. Don't be paralyzed by the choices, especially when you're starting an application. If you begin to feel like you're stuck on this decision, my advice is to pick something you're comfortable with and go that way. Remember, one essential skill of being a developer is learning to balance the tradeoffs that you introduce into your system. If not having the "perfect" stack is causing you to stall out and not write your app, then maybe that's a tradeoff that should be taken more into consideration!

But what do you think? Are you a fan of SPAs? Maybe you wouldn't touch them with a 40-foot pole? Hit me up on Twitter and let me know what you think!

The Links

Join my mailing list!

No spam, just a weekly newsletter with thoughts, discoveries, and cool new things in the world of programming.

subscribe.