What’s the Role of the Server in Single Page Applications (SPAs)?
I’ve been doing a lot of AngularJS consulting and training lately and have been asked one particular question over and over: “What’s the role of the server in Single Page Applications (SPAs)”? Regardless of what SPA framework you use (AngularJS, Ember, Durandal, etc.) every SPA framework out there relies on some type of service (RESTful or otherwise) to serve and process data. That’s the obvious role that servers can play with SPAs. What’s not quite as obvious are the other roles that the server can play as a SPA interacts with it.
Here are a few ideas about roles that a server can play when building SPAs:
Data Service
This is the role that most people think of the server playing with SPAs and definitely the most common role. The server typically exposes a RESTful service to SPA clients to make it easy to GET, PUT, POST, or DELETE data. This can be done using Node.js, ASP.NET Web API, PHP, cloud services like Firebase, and many other frameworks using HTTP, Web Sockets, or another technique. As mentioned earlier, this is the most obvious role played by the server when building SPAs.
In addition to exposing data, the data service is also responsible for providing security as required by a given application.
Data Caching
Some applications consume data that doesn’t change very frequently on the server. This type of data can often be shared across users (product codes, countries, states, departments, locations, etc.). Servers are great at caching data so that queries to the data store are minimized. Whether you’re using Node.js, ASP.NET MVC, PHP, or one of the many other server-side frameworks, you more than likely have access to caching functionality that can increase the scalability of your application significantly. It’s something that I always try to plan for as I think through the role of the server in SPAs and other types of applications. Cache is king (when used appropriately)!
Serving Dynamic Views
Many SPAs load static HTML views from the server that are then processed on the client-side. For example, AngularJS allows views to be associated with routes so that the view can be loaded at runtime when a given route is processed. Here’s an example of defining a route and view (the templateUrl value) using AngularJS:
$routeProvider .when('/customers', { controller: 'CustomersController', templateUrl: '/app/views/customers/customers.html' });
While static HTML views work in many scenarios, there are other scenarios where you may want to load some of the data during the view request, fill in a part of the view with the data, and then send it down to the client for further processing. Why? Doing that can eliminate one or more HTTP calls from the browser to the server to retrieve data (via Ajax, web sockets, etc.). The route shown earlier may be changed to the following to allow for a dynamic view to be generated:
$routeProvider .when('/customers', { controller: 'CustomersController', templateUrl: '/views/customers' });
True, this technique will cause the number of bytes sent from the server to the client to increase, but sometimes reducing the number of HTTP calls can result in a nice performance boost – especially when it comes to mobile devices.
While dynamically generating views and pre-populating them with some of the data certainly isn’t appropriate for every type of SPA out there, some SPAs may benefit from utilizing this type of server-side functionality. Some people may argue that this approach is against the true nature of SPAs but I would argue that every application is unique and there’s no such thing as one size fits all. Pre-filling SPA views with data on the server may be beneficial in some scenarios. Who says that you can’t create what I like to call “mixed mode SPAs” (MM-SPAs….OK I’ll admit that doesn’t exactly role off the tongue :-)) where the server does more than simply serve up data, scripts/styles, and static views?
View Caching
In addition to data caching, the server may also be used to cache HTML views that are retrieved by a SPA. As mentioned earlier, views may be dynamically generated on the server, and in situations where data doesn’t change often and can be shared across users, the views and data may be cached by the server to allow them to be served in a more efficient and scalable manner.
Once views reach the client they can also be cached there of course for scenarios where a “fresh” view isn’t required each time a route is triggered.
Security and Dynamic Views
Security is a key part of many applications. SPAs that load static HTML views from the server more than likely handle security on the client-side (you of course can’t rely on the client for any type of true security) as well as through the data service exposed by the server (where the real security checks should occur). What if your HTML view needs to load specific sections of a view dynamically based upon roles, claim sets, or other types of security constructs?
The server can once again be used to dynamically generate the view based upon specific security requirements. That way HTML fragments aren’t sent down to the client only to be hidden by the SPA framework based upon a user’s role (and easily unhidden by a power user using dev tools). Only the view content that the authenticated and authorized user should see based upon their current roles/permissions is sent down to the browser. I think this is definitely an area where mixed mode SPAs can be very appropriate depending upon the needs and requirements of the application.
Security, Security, Security
I can’t emphasize enough how important the role of the server is when it comes to security. While you can certainly send down roles, permissions, and other security items to the client so that data or HTML fragments can be shown/hidden as appropriate in views, it’s critical that the server validates everything coming back to it.
Browser dev tools make it super easy to tweak HTML, CSS, and JavaScript so storing a user’s security roles on the client (as just one example) is fine but every request to the server should be validated on the server-side to ensure that the user really does have a given role/permission and can perform a specific action. Otherwise, a hacker can easily compromise your application and data by simply changing client-side variables. Using client-side code to secure applications (SPA or otherwise) is not a good way to go and arguably quite irresponsible.
Validation
I normally consider validation to be part of the overall data service component mentioned above but it’s important enough to call it out separately. As with client-side security, client-side validation is a frail solution that can’t stand on its own. All validation of SPA data has to be validated on the server to ensure that the client-side code, and data haven’t been tampered with.
Summary
Is this a complete list of all the ways a server can be used with SPAs? Of course not – this is simply a few things I’ve been thinking about as I’ve interacted with different companies building SPAs. If you have additional ways that you’re using the server with SPA applications leave a comment.
Single Page Applications (SPAs) are great and can provide a unique user experience when built properly. But, switching to SPAs doesn’t mean that all of your server-side skills have to be thrown out the window.