A single-page application (SPA) is a web application or website that interacts with the user by dynamically rewriting the current web page with new data from the web server, instead of the default method of a web browser loading entire new pages. The goal is faster transitions that make the website feel more like a native app.
The origins of the term single-page application are unclear, though the concept was discussed at least as early as 2003. Stuart Morris, a programming student at Cardiff University, Wales, wrote the Self-Contained website at slashdotslash.com with the same goals and functions in April 2002, and later the same year Lucas Birdeau, Kevin Hakman, Michael Peachey and Clifford Yeh described a single-page application implementation in US patent 8,136,109.
There are various techniques available that enable the browser to retain a single page even when the application requires server communication.
HTML authors can leverage element IDs to show or hide different sections of the HTML document. Then, using CSS, authors can use the `#target` selector to only show the section of the page which the browser navigated to.
- AngularJS is a fully client-side framework. AngularJS's templating is based on bidirectional UI data binding. Data-binding is an automatic way of updating the view whenever the model changes, as well as updating the model whenever the view changes. The HTML template is compiled in the browser. The compilation step creates pure HTML, which the browser re-renders into the live view. The step is repeated for subsequent page views. In traditional server-side HTML programming, concepts such as controller and model interact within a server process to produce new HTML views. In the AngularJS framework, the controller and model states are maintained within the client browser. Therefore, new pages are capable of being generated without any interaction with a server.
- ExtJS is also a client side framework that allows creating MVC applications. It has its own event system, window and layout management, state management (stores) and various UI components (grids, dialog windows, form elements etc.). It has its own class system with either dynamic or static loader. The application built with ExtJS can either exist on its own (with state in the browser) or with the server (e.g. with REST API that is used to fill its internal stores). ExtJS has only built in capabilities to use localStorage so larger applications need a server to store state.
- Knockout.js is a client side framework which uses templates based on the Model-View-ViewModel pattern.
WebSockets are a bidirectional real-time client-server communication technology that are part of the HTML5 specification. For real-time communication, their use is superior to Ajax in terms of performance and simplicity.
Server-sent events (SSEs) is a technique whereby servers can initiate data transmission to browser clients. Once an initial connection has been established, an event stream remains open until closed by the client. SSEs are sent over traditional HTTP and have a variety of features that WebSockets lack by design such as automatic reconnection, event IDs, and the ability to send arbitrary events.
Data transport (XML, JSON and Ajax)
Thin server architecture
A SPA moves logic from the server to the client, with the role of the web server evolving into a pure data API or web service. This architectural shift has, in some circles, been coined "Thin Server Architecture" to highlight that complexity has been moved from the server to the client, with the argument that this ultimately reduces overall complexity of the system.
Thick stateful server architecture
This approach needs more server memory and server processing, but the advantage is a simplified development model because a) the application is usually fully coded in the server, and b) data and UI state in the server are shared in the same memory space with no need for custom client/server communication bridges.
Thick stateless server architecture
This approach requires that more data be sent to the server and may require more computational resources per request to partially or fully reconstruct the client page state in the server. At the same time, this approach is more easily scalable because there is no per-client page data kept in the server and, therefore, Ajax requests can be dispatched to different server nodes with no need for session data sharing or server affinity.
Some SPAs may be executed from a local file using the file URI scheme. This gives users the ability to download the SPA from a server and run the file from a local storage device, without depending on server connectivity. If such a SPA wants to store and update data, it must use browser-based Web Storage. These applications benefit from advances available with HTML5.
Challenges with the SPA model
Because the SPA is an evolution away from the stateless page-redraw model that browsers were originally designed for, some new challenges have emerged. Possible solutions (of varying complexity, comprehensiveness, and author control) include:
- Server-side web frameworks that specialize in the SPA model.
- The evolution of browsers and the HTML5 specification, designed for the SPA model.
Between 2009 and 2015, Google Webmaster Central proposed and then recommended an "AJAX crawling scheme" using an initial exclamation mark in fragment identifiers for stateful AJAX pages (
Alternatively, applications may render the first page load on the server and subsequent page updates on the client. This is traditionally difficult, because the rendering code might need to be written in a different language or framework on the server and in the client. Using logic-less templates, cross-compiling from one language to another, or using the same language on the server and the client may help to increase the amount of code that can be shared.
Because SEO compatibility is not trivial in SPAs, it is worth noting that SPAs are commonly not used in a context where search engine indexing is either a requirement, or desirable. Use cases include applications that surface private data hidden behind an authentication system. In the cases where these applications are consumer products, often a classic "page redraw" model is used for the applications landing page and marketing site, which provides enough meta data for the application to appear as a hit in a search engine query. Blogs, support forums, and other traditional page redraw artifacts often sit around the SPA that can seed search engines with relevant terms.
As of version 1.3, ItsNat provides a new stateless mode, and the client DOM is not kept on the server because, with the stateless mode client, DOM state is partially or fully reconstructed on the server when processing any Ajax request based on required data sent by the client informing the server of the current DOM state; the stateless mode may be also SEO-compatible because SEO compatibility happens at load time of the initial page unaffected by stateful or stateless modes. Another possible choice is frameworks like PreRender, Puppeteer, Rendertron which can be easily integrated into any website as a middleware with web server configuration enabling bot requests (google bot and others) to be served by the middleware while non-bot requests are served as usual. These frameworks cache the relevant website pages periodically to allow latest versions be available to search engines. These frameworks have been officially approved by google.
Both of these do require quite a bit of effort, and can end up giving a maintenance headache for the large complex sites. There are also potential SEO pitfalls. If server-generated HTML is deemed to be too different from the SPA content, then the site will be penalized. Running PhantomJS to output the HTML can slow down the response speed of the pages, which is something for which search engines – Google in particular – downgrade the rankings.
Client/server code partitioning
With a SPA being, by definition, "a single page", the model breaks the browser's design for page history navigation using the "forward" or "back" buttons. This presents a usability impediment when a user presses the back button, expecting the previous screen state within the SPA, but instead, the application's single page unloads and the previous page in the browser's history is presented.
Analytics tools such as Google Analytics rely heavily upon entire new pages loading in the browser, initiated by a new page load. SPAs do not work this way.
After the first page load, all subsequent page and content changes are handled internally by the application, which should simply call a function to update the analytics package. Failing to call said function, the browser never triggers a new page load, nothing gets added to the browser history, and the analytics package has no idea who is doing what on the site.
Adding page loads to a SPA
It is possible to add page load events to a SPA using the HTML5 history API; this will help integrate analytics. The difficulty comes in managing this and ensuring that everything is being tracked accurately – this involves checking for missing reports and double entries. Some frameworks provide open source analytics integrations addressing most of the major analytics providers. Developers can integrate them into the application and make sure that everything is working correctly, but there is no need to do everything from scratch.
Speeding up the page load
There are some ways of speeding up the initial load of a SPA, such as a heavy approach to caching and lazy-loading modules when needed. But it's not possible to get away from the fact that it needs to download the framework, at least some of the application code, and will most likely hit an API for data before displaying something in the browser. This is a "pay me now, or pay me later" trade-off scenario. The question of performance and wait-times remains a decision that the developer must make.
This section needs additional citations for verification. (October 2020)
A SPA is fully loaded in the initial page load and then page regions are replaced or updated with new page fragments loaded from the server on demand. To avoid excessive downloading of unused features, a SPA will often progressively download more features as they become required, either small fragments of the page, or complete screen modules.
In this way an analogy exists between "states" in a SPA and "pages" in a traditional website. Because "state navigation" in the same page is analogous to page navigation, in theory, any page-based web site could be converted to single-page replacing in the same page only the changed parts.
- "Inner-Browsing: Extending Web Browsing the Navigation Paradigm". Retrieved February 3, 2011.
- "Slashdotslash.com: A self contained website using DHTML". Retrieved July 6, 2012.
- "US patent 8,136,109". Retrieved April 12, 2002.
- "Meteor Blaze". GitHub.
Blaze is a powerful library for creating user interfaces by writing reactive HTML templates.
- Introducing DDP, March 21, 2012
- "Server Side Rendering for Meteor". Archived from the original on March 20, 2015. Retrieved January 31, 2015.
- "Single-page applications vs. multiple-page applications: pros, cons, pitfalls - BLAKIT - IT Solutions". blak-it.com. BLAKIT - IT Solutions. October 17, 2017. Retrieved October 19, 2017.
- "Real-Time Monitoring using AJAX and WebSockets". www.computer.org. Retrieved June 1, 2016.
- "Server-Sent Events". W3C. July 17, 2013.
- "Unhosted web apps".
- "The Single Page Interface Manifesto". Retrieved April 25, 2014.
- "Derby". Retrieved December 11, 2011.
- "Sails.js". GitHub. Retrieved February 20, 2013.
- "Tutorial: Single Page Interface Web Site With ItsNat". Retrieved January 13, 2011.
- "What the user sees, what the crawler sees". Retrieved January 6, 2014.
- "Making Ajax Applications Crawlable". Retrieved January 6, 2014.
Historically, Ajax applications have been difficult for search engines to process because Ajax content is produced
- "Proposal for making AJAX crawlable". Google. October 7, 2009. Retrieved July 13, 2011.
- "(Specifications) Making AJAX Applications Crawlable". Google Inc. Retrieved March 4, 2013.
- "Hash URIs". W3C Blog. May 12, 2011. Retrieved July 13, 2011.
- "Deprecating our AJAX crawling scheme". Official Google Webmaster Central Blog. Retrieved February 23, 2017.
- "Implement dynamic rendering". Google Search Central. October 13, 2018. Retrieved January 7, 2021.
- "ItsNat v1.3 release Notes". Retrieved June 9, 2013.
- Holmes, Simone (2015). Getting MEAN with Mongo, Express, Angular, and Node. Manning Publications. ISBN 978-1-6172-9203-3
- "Single Page Applications (SPA)". Appcheck Ltd.