In this post, I'll pick up where Brandon left off in Web Application Types (Part 1) and take a deeper dive into the client-side single-page application, commonly abbreviated as “SPA”. What is considered an SPA? What are important choices to be made when building one? How do you deploy it? When is an SPA a good choice or a bad choice? Let’s dive in and find out.
An SPA can be thought of as a thick client that uses the browser as an application platform. The responsibility for displaying views to the user is handled in the browser and the back end’s sole purpose is to respond to requests for data. The SPA uses the responses from the server and updates the view by modifying the live HTML client-side to reflect those responses.
I won’t attempt to suggest the “right” framework choice here as the Internet is full of debates on the subject. The right choice depends on a lot of factors, including personal preferences, team skill sets, and project requirements. There is no one-size-fits-all. That being said, for the kind of complex interfaces Expero typically tackles, we prefer to use React paired with Redux for state management, but we routinely tackle projects using other frameworks as well, notably Angular. React is backed by Facebook and brings with it a thriving ecosystem of libraries and tools to add on functionality as you go.
Furthermore, the naive construction of a web application results in thousands of files that would result in a very inefficient delivery to the browser, so we want to compress them both in number and size.
Another common task of the build process is to include some unique identifier in the deployment file names, commonly a hash of the contents or a timestamp. This enables static files to be cached for a long time, while still providing a way to break the cache when changes are made (more on this later). This has two major benefits: 1. Server load is reduced thanks to caches short-circuiting frequent file requests, and 2. Your support team will never have to tell your customers to “clear their browser cache” in order to see updates.
Common build tools in use today include Webpack, Grunt, and Gulp. The choice of framework or programming language may already dictate your chosen build tool. Angular, for example, provides its own build system. Webpack is often used for React-based applications.
SPAs are very flexible when it comes to deploying to a server. As long as the server can deliver a collection of static files, then it can host a single-page application. This is important because it means you can cleanly decouple your back end from the client’s view and architect the back end any way you choose. You may want to keep things simple and host the front end on the same server that handles requests for data or you might have a large ecosystem of load-balanced microservices and choose to serve the front end from a highly available CDN. It makes little difference to the overall architecture and design of the client-side application.
We’re fans of Amazon Web Services. Here’s an example deployment using Amazon’s S3 service.
In this model, the concerns of serving www.foo.com are completely separate from any requests for data through an API server. Both can be managed and optimized for their intended purpose. In the case of the file server, S3 buckets can be configured for website hosting and serve all the static files that make up the SPA. As mentioned earlier, aggressive caching headers can be set to further speed up client load times and reduce server load if unique hashes (or some other cache break technique) were implemented as part of the build process.
This separation completely eliminates a chunk of work for the back end. Pure data services typically should not allow the client to perform any caching in order for client applications to always receive fresh data. Furthermore, the scaling and division of responsibilities among services is not mixed up with the concerns of serving the client-facing URL.
Single-page apps are a must when a responsive and interactive in-browser user experience is required. The classic server-based approach to updating a page in response to a user interaction is painfully slow by today’s standards. Each change to the view requires a complete page reload, which incurs a lot of overhead. The single-page app only pays the page load penalty one time, and further changes are incremental modifications to the live document.
The separation between front end and back end also tends to lead to a clean API that can be reused for native mobile applications. In many cases, the single-page app itself can be repackaged as the mobile application.
Security is also a concern with an SPA. All the code running on the browser can be easily inspected by a tech-savvy user. A build process that minifies the code may provide some level of obfuscation, but that’s not true security. Any sensitive information, calculations, etc. are best kept exclusively on the server. User input validation is a common example of something that should ALWAYS run on a server and not depend on client code that could be bypassed in order to prevent bad things from happening. This doesn’t necessarily rule out an SPA, but it does mean care must be taken when designing the system in order to keep sensitive code away from the client.
The modern single-page application has become a first-class citizen next to native desktop and mobile applications in what is now possible with a web browser. This is a constantly evolving field, and what is trendy and in fashion today might be old news six months to a year later. At Expero, we love to keep up with this ever-changing field and bring that experience to our clients.
This post has only scratched the surface on today’s single-page applications. Since SPAs are still relatively new, many existing applications are still using older approaches and struggling to deliver performant user experiences. If you're sold on building an SPA, then keep a lookout for an upcoming post from us that discusses what you should consider when modernizing your existing application.