When the web was young, it was simple, it was stateless. It was originally envisioned by its creators as a set of hypertext documents linked together. Then, somebody added a forms tag and the era of web applications has begun.
Nowadays, web applications could be as complex as needed. Pretty much any kind of application could be implemented as web application. But advanced functionality requires advanced application architecture and design. There are two corner-stone design patterns for web applications – multi page web applications (MPA) and single page web applications (SPA).
MPA is traditional kind of web applications. Every time application needs to submit user input to the web server or needs to display new data to user, it have to request a new page from the server and then render it in the web browser. This approach works fine for simple pages, but when the application have a rich user interface, then pages may become very complex and loaded with a lot of data. Generating complex web pages on the server, transmitting them over the internet and rendering in the browser takes time and thus degrades user experience, because user can’t continue working with application while it’s in process of serving a new page. In the beginning of 2000s MPA were improved with AJAX technology, which allows to refresh parts of the page without reloading the whole page. That definitely makes user experience better, but it adds complexity to the page.
SPAs emerged in early 2010s. SPA is essentially an evolution of MPA+AJAX design pattern, where only one simple “shell” page is generated on the server (for bootstrapping an application), and all UI is rendered by browser scripts (JavaScript). I.E. instead of requesting pages or page fragments from the server, SPAs request markup and data separately from the server and render pages directly in browser. SPAs were made possible by advanced MVVM javascript frameworks like angular.js and knockout.js.
SPAs have the following advantages over MPAs:
– faster page loading times. Because page rendering happen on the client, less data travels over the wire and thus page loads faster. This is especially noticeable over slower networks, like mobile.
– improved user experience. Because it’s possible to data from the server in background, the application is always available for the user.
– simplified and streamlined development. No need to write code to render pages on the server.
– decoupling of frontend and backend development. Because backend is no longer responsible for rendering UI, UI development could be handled without dependency from backend development.
– simplified mobile development. Same backend could be used for web application and for a native mobile application.
– better unit-test-ability of UI and backend code
SPA have the following disadvantages to MPAs:
– heavy client frameworks. SPAs require use of advanced JavaScript frameworks which have to be loaded on a client which could lead for a potentially slower application initialization
– UI code is not compiled, so it’s somewhat harder to debug and also it’s exposed to potential malicious user
In my experience I often see MPA and SPA patterns mixed together, so we have a MPA application (as a safer and more traditional pattern) where one of the pages is implemented as SPA. This hybrid approach is usually doesn’t provide benefits of either MPA not SPA and combines disadvantages of each other.
The hybrid application:
– loads pages slowly because both pre-renderd markup AND heavy client frameworks are loaded to the client
– have complicated development environment, because developer have to use TWO development frameworks (usually both client MVVM and server-side MVC frameworks)
– tightly coupled frontend and backend development
– same backend can’t be used from mobile application
– UI unit testing is complicated
Considering all of the above I’d like to warn against mixing MPA and SPA approaches in the same application. Each pattern is good for its use case, but mixing them together doesn’t produce an optimal result.
I was actually about to MIX MPA AND SPA. Your post gives me the complete idea that I should not do that
Thanks again
But if my SPA has 30 unique urls i.e. sections wont it be prone to memory leaks and insanely slow initial load? instead breaking the application into multiple SPA will be beneficial isn’t it?
I’d not be worried about memory leaks – unless browser has bugs (and we all hope that there are no bugs :)) then there should be no memory leaks.
Initial load timing could be helped by:
– dynamic load of the asserts. Most modern MVVM frameworks are loading views dynamically. Require.js can load scripts dynamically.
– script minification
Although, if your application is insanely massive, then maybe if would make sense to break it down into a few smaller SPAs.
it seems these guys ripped off your article…
http://www.eikospartners.com/blog/multi-page-web-applications-vs.-single-page-web-applications
Thank you for noticing it, Alejandro!
Well, I guess that means my blog post wasn’t that bad. 🙂
I agree that SPAs give you the speed advantage but should speed be your only major concern? How about security? Will the speed of your pages outrun an attacker? You left out one of the biggest issues with SPAs and that is too much transparency in what your application is doing. At what point do you decide what lives on the client or what lives on the server? Do you want to clutter your client with code like this?
if(Role.isAdmin(user)) { router.goto(‘/admin’) }
What if you have situations where you are planning a multi tenant SAAS application where your users can have different subscriptions types? Do you want to keep checks like what features should be shown (based on their subscription package) on the client? What if you only want the client to view sections only pertaining to what the they paid for? Would you rather load the entire codebase into a basic user’s web browser and switching off UI elements one by one with a code similar to the one above? Going full SPA does not always make sense depending on the complexity/requirements of the application. one of the most elegant way to do it would be to go hybrid in my opinion.
An SPA is just a pattern and not an Iron rule and i believe it’s okay to mix it where it makes sense.
The more important difference of spa and mpa is that mpa is way easier/better with seo than spa. The point is, that seo requires the presence of deeplinks, and the landing page can be expected in the depths of the application instead of the front page – which is commonly assumed with an spa. The hibrid solution would be that the server side renders (deeplinked) pages on the server side, but armed with a js framework, so that the user wouldn’t load any more pages, the rest of the content are accessed though ajax and javascript DOM manipulation.
Another seo problem with spa is that content should be more specific under a given url. Single page applications tend to scroll to different content instead of paging, but this will mix the various contents of the page, and make it less relevant for search engines.
I have been part of two separate codebases which use hybrid approaches… I think you need a high threshold for pain if you take this approach.