A Blended Single Page and Multi Page Application Approach
It’s no secret that the web development community is a fast-moving hype train, with new frameworks, libraries, and tools released at a dizzying pace. In parallel, there are many blogs vying for your time and attention, many touting the latest library they have picked up is the next big thing. This blog post is not about relishing in the next hot framework, but rather a reflection piece on the development of single-page applications (SPAs) and multi-page applications (MPAs), as well as the current state of the server-side and client-side frameworks that support these paradigms. Importantly, this post provides a case that MPAs still have relevance in the right problem domain and runs through a short example on how the best of both of these worlds can be had using a blended framework approach.
Single Page Applications
The rise of the Single Page Application (SPA) paradigm kicked off the development of a plethora of front-end frameworks, aiming to reduce the amount of JavaScript code required to develop a web application that is reliable and scalable:
SPAs ultimately exist to provide a more seamless User Experience (UX) in applications that require the user to complete numerous actions on the same page without a full reload of the HTML and resources, which results in the visible outcomes of both latency and in many cases, the layout of the page being reset. The avoidance of the page reload allows web apps to function in a way more akin to their native software cousins and allows a user to be more productive when completing common tasks. The other situation where SPAs really shine is apps that require “real-time” interface updates, these types of applications may be updating data within the UI multiple times per second and would be unusable using a traditional page reload to present updated data to a user.
The improved user experience comes with a trade-off of slower initial page load times due to the user’s browser having to load the library code fully before rendering the final page for the user to view. For this reason, these types of application aren’t well suited for casual users that will bounce from a site that loads slowly. Another, more development focused, the disadvantage of SPAs is having to maintain state between the server and the client, with development for the latter lacking compile-time checks for broken references, type checking etc. However it is worth noting that some of these disadvantages can be addressed through the use of libraries, tests and languages that transpile to JavaScript, e.g. TypeScript.
Multi Page Applications
The only type of website in the early days of the internet is what now is sometimes referred to as a multi-page Application (MPA). An MPA requires the browser to download all resources (HTML, CSS, JS, images etc.) on each page load, however, the user is presented the main page content upfront with styling and other functionality progressively loaded. MPAs are well suited to web sites that are largely content focused as they scale well due to each page being accessible as a standalone document, and benefit from having a well laid out navigation hierarchy that separates content in a logical way for a user. MPAs also offer the advantage of allowing to write the bulk of your code in your language of choice, whereas for the time being SPAs are limited to JavaScript (or things can be compiled into JavaScript). Some examples of popular server-side languages and frameworks are:
- Java: Spring, Java Server Faces, Google Web Toolkit
- C#: ASP.NET, ASP.NET MVC. Nancy
- JavaScript (Node.js): Express. Sails, Koa
- PHP: Laravel, Code Igniter, Symfony
- Python: Django, Flask, Tornado
- Ruby: Ruby on Rails, Sinatra, Hanami
A Blended Approach
Over the last few years there has been a notable shift in the web development community toward the use of a SPA architecture and development workflow with the server side reduced to providing a web application programming interface (API) for the front end to access the persistent data. The flipside is only doing server-side templating and using an MPA approach. Although there are cases where these architectural approaches are the best fit, it is important to consider a third approach, which is using a blend of the two. This approach is a good fit for situations where you have a lot of content to deliver, but want some of your pages to be interactive and/or have real-time content updates. It is worth noting that undertaking a blended approach can increase development time due to your developers having to understand and develop using two frameworks. Despite this, we found that delivering content using distinct pages where the majority of content did not need to be loaded asynchronously simplified the development process and reduced maintenance overhead, ultimately leading to greater productivity and fewer bugs.
A Case for a Blended Approach
A recent project we worked on contained a number of configuration and data-centric pages to be displayed to the user, which lent themselves to a more traditional MPA server-side templating approach. The project used Spring Boot along with Thymeleaf to deliver these pages, which allowed us to rapidly build out a web frontend that served its purpose very well. However, on one page of the interface, we were required to have a number of widgets and charts that would update in real time, alongside other static data on the page.
To achieve the desired blend of static and dynamic page content we looked to Vue as it could be incorporated into our existing development pipeline without having to drastically change our build process or architectural approach. We could use Vue instances in the areas of the page where we needed real-time updates, whilst continuing to load the more static data on the same page leveraging the Thymeleaf templates for the initial page load. The other library we used was ChartJS for the charting component. The flexibility Vue provides by not taking over the entire DOM allowed us to keep the charts updating natively without having to rely on a plugin that wrapped the library up, and would require ongoing maintenance to keep everything in check. A high-level example of a page breakdown with static Thymeleaf rendered content + dynamic charts handled by ChartJS + dynamic widgets/components with Vue can be seen graphically below.
The Thymeleaf + Vue combination worked well for our project and allowed for blending Thymeleaf and Vue bindings on the same HTML elements for initialising values of components on page load without fetching via AJAX. For example in the below snippet uses the Thymeleaf template engine to embed the User Account ID into the template, which in turn allows Vue to bind the ID for use within the alert-button Vue component:
<alert-button v-bind:alert="alert"
v-bind:user-id="${user.getUserAccountId()}"
v-on:update:alert="alert = $event">
</alert-button>
Overall, using a blend of tools and technologies from the MPA and SPA worked well for our recent project, and we were able to leverage the advantages of each approach to our benefit. Although the example above uses Thymeleaf + Vue, the blended approach could be achieved using other desired frameworks that can live harmoniously in one project. As a recommendation, it is always worth analysing the pros and cons of each approach before diving into development for your next project, and you may find—as we did—that a blended approach can allow you to have your cake and eat it too.
Header image courtesy of Roman Serdyuk.