Open main menu

A single-page application (SPA) is a web application or web site that interacts with the user by dynamically rewriting the current page rather than loading entire new pages from a server. This approach avoids interruption of the user experience between successive pages, making the application behave more like a desktop application. In a SPA, either all necessary code – HTML, JavaScript, and CSS – is retrieved with a single page load,[1] or the appropriate resources are dynamically loaded and added to the page as necessary, usually in response to user actions. The page does not reload at any point in the process, nor does control transfer to another page, although the location hash or the HTML5 History API can be used to provide the perception and navigability of separate logical pages in the application.[2] Interaction with the single page application often involves dynamic communication with the web server behind the scenes.


The origins of the term single-page application are unclear, though the concept was discussed at least as early as 2003.[3] Stuart (stunix) Morris wrote the Self-Contained website at with the same goals and functions in April 2002,[4] 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.[5]

JavaScript can be used in a web browser to display the user interface (UI), run application logic, and communicate with a web server. Mature open-source libraries are available that support the building of an SPA, reducing the amount of JavaScript code developers have to write.

Technical approachesEdit

There are various techniques available that enable the browser to retain a single page even when the application requires server communication.

JavaScript frameworksEdit

Web browser JavaScript frameworks, such as AngularJS, Ember.js, ExtJS, Knockout.js, Meteor.js, React and Vue.js have adopted SPA principles.

  • 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.
  • Ember.js is a client-side JavaScript web application framework based on the model–view–controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.
  • 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.
  • Meteor.js is a full-stack (client-server) JavaScript framework designed exclusively for SPAs. It features simpler data binding than Angular, Ember or ReactJS,[6] and uses the Distributed Data Protocol[7] and a publish–subscribe pattern to automatically propagate data changes to clients in real-time without requiring the developer to write any synchronization code. Full stack reactivity ensures that all layers, from the database to the templates, update themselves automatically when necessary. Ecosystem packages such as Server Side Rendering[8] address the problem of Search Engine Optimization.
  • React (sometimes styled React.js or ReactJS) is a JavaScript library for building user interfaces. It is maintained by Facebook, Instagram and a community of individual developers and corporations. React uses a new language which is a mix of JS and HTML (a subset of HTML). Several companies use React with Redux (JavaScript library) which adds state management capabilities, which (with several other libraries) lets developers create complex applications.[9]
  • Vue.js (commonly referred to as Vue; pronounced /vjuː/, like view) is an open-source progressive JavaScript framework for building user interfaces. Vue developers also provide Vuex for state management.


The most prominent technique currently being used is Ajax.[1] Predominantly using the XMLHttpRequest/ActiveX Object(deprecated) object from JavaScript, other Ajax approaches include using IFRAME or script HTML elements. Popular libraries like jQuery, which normalize Ajax behavior across browsers from different manufacturers, have further popularized the Ajax technique.


WebSockets are a bidirectional real-time client-server communication technology part of the HTML5 specification, superior to Ajax in terms of performance[10] and simplicity.

SPA with Ajax and WebsocketsEdit

WebSockets are typically used in applications where real time updates are required . WebSockets also enables us to multiplex data on the same connection, thus one can easily implement an 'AJAX library on top of WebSockets[11]' and still use the same WebSocket connection for bi-directional real-time data transfer.

Server-sent eventsEdit

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.[12]

Browser pluginsEdit

Although this method is outdated, asynchronous calls to the server may also be achieved using browser plug-in technologies such as Silverlight, Flash, or Java applets.

Data transport (XML, JSON and Ajax)Edit

Requests to the server typically result in either raw data (e.g., XML or JSON), or new HTML being returned. In the case where HTML is returned by the server, JavaScript on the client updates a partial area of the DOM (Document Object Model).[13] When raw data is returned, often a client-side JavaScript XML / (XSL) process (and in the case of JSON a template) is used to translate the raw data into HTML, which is then used to update a partial area of the DOM.

Server architectureEdit

Thin server architectureEdit

An 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 architectureEdit

The server keeps the necessary state in memory of the client state of the page. In this way, when any request hits the server (usually user actions), the server sends the appropriate HTML and/or JavaScript with the concrete changes to bring the client to the new desired state (usually adding/deleting/updating a part of the client DOM). At the same time, the state in server is updated. Most of the logic is executed on the server, and HTML is usually also rendered on the server. In some ways, the server simulates a web browser, receiving events and performing delta changes in server state which are automatically propagated to client.

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 architectureEdit

This is a variant of the stateful server approach. The client page sends data representing its current state to the server, usually through Ajax requests. Using this data, the server is able to reconstruct the client state of the part of the page which needs to be modified and can generate the necessary data or code (for instance, as JSON or JavaScript), which is returned to the client to bring it to a new state, usually modifying the page DOM tree according to the client action which motivated the request.

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.

Running locallyEdit

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 an SPA wants to store and update data, it must use browser-based Web Storage. These applications benefit from advances available with HTML5.[14]

Challenges with the SPA modelEdit

Because the SPA is an evolution away from the stateless page-redraw model that browsers were originally designed for, some new challenges have emerged. Each of these problems has an effective solution[15] with:

  • Client-side JavaScript libraries addressing various issues.
  • Server-side web frameworks that specialize in the SPA model.[16][17][18]
  • The evolution of browsers and the HTML5 specification designed for the SPA model.[19]

Search engine optimizationEdit

Because of the lack of JavaScript execution on crawlers of some popular Web search engines,[20] SEO (Search engine optimization) has historically presented a problem for public facing websites wishing to adopt the SPA model.[21]

Between 2009 and 2015, Google Webmaster Central proposed and then recommended an "AJAX crawling scheme"[22][23] using an initial exclamation mark in fragment identifiers for stateful AJAX pages (#!). Special behavior must be implemented by the SPA site to allow extraction of relevant metadata by the search engine's crawler. For search engines that do not support this URL hash scheme, the hashed URLs of the SPA remain invisible. These "hash-bang" URIs have been considered problematic by a number of writers including Jeni Tennison at the W3C because they make pages inaccessible to those who do not have JavaScript activated in their browser. They also break HTTP referer headers as browsers are not allowed to send the fragment identifier in the Referer header.[24] In 2015, Google deprecated their hash-bang AJAX crawling proposal.[25]

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.

Another approach used by server-centric web frameworks like the Java-based ItsNat is to render any hypertext on the server using the same language and templating technology. In this approach, the server knows with precision the DOM state on the client, any big or small page update required is generated in the server, and transported by Ajax, the exact JavaScript code to bring the client page to the new state executing DOM methods. Developers can decide which page states must be crawlable by web spiders for SEO and be able to generate the required state at load time generating plain HTML instead of JavaScript. In the case of the ItsNat framework, this is automatic because ItsNat keeps the client DOM tree in the server as a Java W3C DOM tree; rendering of this DOM tree in the server generates plain HTML at load time and JavaScript DOM actions for Ajax requests. This duality is very important for SEO because developers can build with the same Java code and pure HTML-based templating the desired DOM state in server; at page load time, conventional HTML is generated by ItsNat making this DOM state SEO-compatible. As of version 1.3,[26] 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.

There are a couple of workarounds to make it look as though the web site is crawlable. Both involve creating separate HTML pages that mirror the content of the SPA. The server could create an HTML-based version of the site and deliver that to crawlers, or it's possible to use a headless browser such as PhantomJS to run the JavaScript application and output the resulting HTML.

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.[27]

Client/Server code partitioningEdit

One way to increase the amount of code that can be shared between servers and clients is to use a logic-less template language like Mustache or Handlebars. Such templates can be rendered from different host languages, such as Ruby on the server and JavaScript in the client. However, merely sharing templates typically requires duplication of business logic used to choose the correct templates and populate them with data. Rendering from templates may have negative performance effects when only updating a small portion of the page—such as the value of a text input within a large template. Replacing an entire template might also disturb a user's selection or cursor position, where updating only the changed value might not. To avoid these problems, applications can use UI data bindings or granular DOM manipulation to only update the appropriate parts of the page instead of re-rendering entire templates.

Browser historyEdit

With an SPA being, by definition, "a single page", the model breaks the browser's design for page history navigation using the Forward/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.

The traditional solution for SPAs has been to change the browser URL's hash fragment identifier in accord with the current screen state. This can be achieved with JavaScript, and causes URL history events to be built up within the browser. As long as the SPA is capable of resurrecting the same screen state from information contained within the URL hash, the expected back button behavior is retained.

To further address this issue, the HTML5 specification has introduced pushState and replaceState providing programmatic access to the actual URL and browser history.


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 an SPAEdit

It is possible to add page load events to an 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.[27]

Speed of initial loadEdit

Single Page Applications have a slower first page load than server-based applications. This is because the first load has to bring down the framework and the application code before rendering the required view as HTML in the browser. A server-based application just has to push out the required HTML to the browser, reducing the latency and download time.

Speeding up the page loadEdit

There are some ways of speeding up the initial load of an 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.[27] 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.

Page lifecycleEdit

An 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, an 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 an 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 result of comparing consecutive pages in a non-SPA.

The SPA approach on the web is similar to the Single Document Interface (SDI) presentation technique popular in native desktop applications.

See alsoEdit


  1. ^ a b Flanagan, David, "JavaScript - The Definitive Guide", 5th ed., O'Reilly, Sebastopol, CA, 2006, p.497
  2. ^ "Fixing the Back Button: SPA Behavior using Location Hash". Falafel Software Blog. Retrieved 2016-01-18.
  3. ^ "Inner-Browsing: Extending Web Browsing the Navigation Paradigm". Retrieved 2011-02-03.
  4. ^ " A self contained website using DHTML". Retrieved 2012-07-06.
  5. ^ "US patent 8,136,109". Retrieved 2002-04-12.
  6. ^ "Meteor Blaze". Meteor Blaze is a powerful library for creating live-updating user interfaces. Blaze fulfills the same purpose as Angular, Backbone, Ember, React, Polymer, or Knockout, but is much easier to use. We built it because we thought that other libraries made user interface programming unnecessarily difficult and confusing.
  7. ^ Introducing DDP, March 21, 2012
  8. ^ "Server Side Rendering for Meteor". Archived from the original on 20 March 2015. Retrieved 31 January 2015. Cite uses deprecated parameter |deadurl= (help)
  9. ^, BLAKIT, (2017-10-17). "Single-page applications vs. multiple-page applications: pros, cons, pitfalls - BLAKIT - IT Solutions". BLAKIT - IT Solutions. Retrieved 2017-10-19.CS1 maint: extra punctuation (link)
  10. ^ "Real-Time Monitoring using AJAX and WebSockets". Retrieved 2016-06-01.
  11. ^ "AJAX over WebSockets". / Retrieved 2018-11-01.
  12. ^ "Server-Sent Events". W3C. 17 July 2013.
  13. ^ "Using InnerHTML". Retrieved 2016-01-21.
  14. ^ "Unhosted web apps".
  15. ^ "The Single Page Interface Manifesto". Retrieved 2014-04-25.
  16. ^ "Derby". Retrieved 2011-12-11.
  17. ^ "Sails.js". Retrieved 2013-02-20.
  18. ^ "Tutorial: Single Page Interface Web Site With ItsNat". Retrieved 2011-01-13.
  19. ^ HTML5
  20. ^ "What the user sees, what the crawler sees". Retrieved January 6, 2014. the browser can execute JavaScript and produce content on the fly - the crawler cannot
  21. ^ "Making Ajax Applications Crawlable". Retrieved January 6, 2014. Historically, Ajax applications have been difficult for search engines to process because Ajax content is produced
  22. ^ "Proposal for making AJAX crawlable". Google. October 7, 2009. Retrieved July 13, 2011.
  23. ^ "(Specifications) Making AJAX Applications Crawlable". Google. Retrieved March 4, 2013.
  24. ^ "Hash URIs". W3C Blog. May 12, 2011. Retrieved July 13, 2011.
  25. ^ "Deprecating our AJAX crawling scheme". Official Google Webmaster Central Blog. Retrieved 2017-02-23.
  26. ^ "ItsNat v1.3 release Notes". Retrieved 2013-06-09.
  27. ^ a b c Holmes, Simone (2015). Getting MEAN with Mongo, Express, Angular, and Node. Manning Publications. ISBN 978-1-6172-9203-3

External linksEdit