单页应用

历史

尽管早在2003年就讨论过这个概念，但单页应用（single-page application）一词的起源并不明晰。Stuart (stunix) Morris在2002年4月编写的自主网站slashdotslash.com有着相同的目标和功能；同年稍晚，Lucas Birdeau、Kevin Hakman、Michael Peachey和Evan Yeh在美国专利8,136,109中描述了一个单页应用程序的实现。
在网页浏览器中可以使用JavaScript显示用户界面（UI）、运行应用程序逻辑，以及与Web服务器通信。成熟的开源库支持构建一个单页应用，从而减少开发人员要编写的JavaScript代码量。

技术举措

现今已有各种技术可以使网页浏览器停留在单个页面，并同时支持应用程序与服务器通信。

Ajax

当前最常采用Ajax技术。主要从JavaScript使用XMLHttpRequest/ActiveX对象（已不建议使用），其他Ajax方法包括使用IFRAME或script HTML元素。jQuery等流行的库可以为不同厂商的浏览器的Ajax行为标准化，进一步推广了Ajax技术。

Websocket

WebSocket是HTML5规范中的一个双向有状态实时客户端与服务器通信技术，在性能和简单性方面优于Ajax。

服务器发送事件

服务器发送事件（SSE）是一种服务器向浏览器客户端发起数据传输的技术。一旦创建了初始连接，事件流将保持打开状态，直到客户端关闭。该技术通过传统的HTTP发送，并具有WebSockets缺乏的各种功能，例如自动重新连接、事件ID以及发送任意事件的能力。

浏览器插件

可以使用浏览器插件技术（如Silverlight、Flash或Java applet）实现对服务器的异步调用。此种方法在业界已经过时。

数据传输（XML、JSON和Ajax）

对服务器的请求通常会带来原始数据（如XML或JSON）或新HTML的返回。在服务器返回HTML时，客户端上的JavaScript将更新DOM的部分区域。在返回原始数据时，客户端侧的JavaScript通常将其转换为HTML，然后用它来更新DOM的部分区域。

瘦服务器架构

SPA技术将逻辑从服务器转移到了客户端。这导致Web服务器发展为一个纯数据API或Web服务。这种架构的转变在一些圈子中被称为“瘦服务器架构”，以强调复杂性已从服务端转移到客户端，并认为这最终降低了系统的整体复杂性。

胖的有状态服务器架构

这种设计是服务器在内存中保存必要的客户端所处状态。这种模式下，当任何请求到达服务器（通常因用户操作）时，服务器发送适当的HTML和/或JavaScript，以及具体的更改，以使客户端达到新的期望状态（如添加、删除或更新部分客户端的DOM）。与此同时更新服务器中的状态。这种设计下的大部分逻辑都在服务器上运行，HTML通常也在服务器上呈现。在某些方面，服务器是模拟Web浏览器，接收事件并执行服务器状态下的增量更改，将这些更改自动传播到客户端。
这种方法需要更多的服务器内存和处理能力，但优点是简化的开发模型，因为：1、应用程序通常完全在服务器中编写；2、服务器中的数据和UI状态在相同的内存空间中共享，不需要自定义客户端/服务器通信隧道。

胖的无状态服务器架构

这是有状态服务器方法的变体。客户端页面通常通过Ajax请求将表示其当前状态的数据发送到服务器。服务器使用这些数据能够重新构建需要修改的页面部分，并生成必要的数据或代码（如作为JSON或JavaScript），将其返回给客户端使其它达到新的状态。
此方法需要将更多数据发送给服务器，并可能需要更多计算资源才能部分或完全重建在服务器中的客户端页面状态。不过，这种方法更容易扩展，因为服务器中不存在每个客户端的页面数据，因此可以将Ajax请求分派到不同的服务器节点，而无需会话数据共享或服务器关联。

本地运行

部分单页应用可以使用file URI方案依赖本地文件运行。这使用户可以从服务器上下载单页应用并在本地设备中运行，而不需要依赖与服务器的网络连接。这类单页应用如果想要存储或更新数据，则必须使用基于浏览器的网页存储。这些应用受益于HTML5提供的高级功能。

搜索引擎优化

由于一些流行的网络搜索引擎的爬虫缺乏JavaScript执行能力，搜索引擎最优化（SEO）已成为面向公众的网站采用单页应用模型必须面对的一个问题。
在2009至2015年间，Google网站管理员提出并推荐了一个“AJAX爬取方案”，其中使用起始为感叹号的片段标识符（#!）来标识有状态的AJAX页面。单页应用网站必须实现特殊行为才能允许搜索引擎的爬取工具提取相关的元数据。对于不支持此URL散列方案的搜索引擎，单页应用的散列网址会被视而不见。包括Jeni Tennison在内的许多作者认为这些“hash-bang”URI在W3C中被认为是存在问题的，因为它们使那些没有在浏览器中激活JavaScript的人无法访问页面。这也影响HTTP引用地址头，因为浏览器不允许在Referer头中发送片段标识符。2015年，Google不再建议使用散列AJAX爬取方案。
还有一些周边方法可以使网站表现为可抓取，它们都涉及创建反应单页应用内容的独立HTML页面。服务器可以创建基于HTML的网站版本并将此提供给爬取工具，也可以使用PhantomJS等无头浏览器运行JavaScript应用程序并输出生成的HTML。
这种方法需要付出不小的努力，最终可能给大型、复杂的网站带来很大的 维护成本，并且也有潜在风险。如果服务器生成的HTML被认为与单页应用存在较大差异，则网站排名将受到处罚。运行PhantomJS来输出HTML可能会降低页面的响应速度，一些搜索引擎（尤其是Google）可能因此对排名降级。

客户端/服务器代码分区

增加服务器与客户端之间所共享代码量的一种方法是使用如Mustache、Handlebars等无逻辑模板语言。这种模板可以用不同的托管语言来呈现，如服务器上的Ruby和客户端的JavaScript。但是，单纯共享模板通常需要重复使用业务逻辑来选择正确的模板，并使用数据填充它们。仅更新页面的一小部分（诸如大型模板中的一个文本的值）时，从模板呈现可能会产生负面的性能影响。替换整个模板也可能会干扰用户的选择或光标位置，只更新变更的值则可能不会。为避免这些问题，应用程序可以使用UI数据绑定或粒度DOM操作来更新页面的相应部分，而不是重新呈现整个模板。

浏览器历史记录

根据单页应用（SPA）模型的定义，它只有“单个页面”，因此这打破了浏览器为页面历史记录导航所设计的“前进/后退”功能。当用户按下后退按钮时，可能会遇到可用性障碍，页面可能返回真正的上一个页面，而非用户所期望的上一个页面。
传统的解决方案是不断更改浏览器网址（URL）的散列片段标识符以保持与当前的屏幕状态一致。这种方案可以通过JavaScript实现，并在浏览器中创建起网址历史事件。只要单页应用能根据网址散列所包含的信息重新生成相同的屏幕状态，就能实现预期的后退按钮行为。
而为进一步解决此问题，HTML5规范引入了pushState和replaceState来提供代码对实际网址和浏览器历史的访问。

分析

诸如Google分析等分析工具高度依赖在浏览器中加载全新的页面，而单页应用的工作方式不同于此。

初次加载的速度

单页应用的第一页加载会比基于服务器的应用慢。这是因为首次加载必须先拿到框架和应用程序的代码，再在浏览器中呈现所需的视图。基于服务器的应用程序只需将所需的HTML推送到浏览器，从而减少了延迟和下载用时。

加快页面加载速度

有一些方法可以加快单页应用的初次加载速度，比如采用多项缓存措施、需要时再加载某些模块（懒加载）。但这依旧不可能摆脱需要下载框架的事实，某些部分必须在呈现前下载。这是一个“现在支付，或者稍后支付”的问题。性能与等待时间的权衡是开发者必须作出的权衡。

页面生命周期

单页应用在初始页面加载时被完全加载，然后页面区域被替换或更新为按需从服务器加载的新页面片段。为避免过度下载未使用的功能，单页应用通常会逐渐下载更多内容，如所需要的功能、页面的一小块，或者完整的一页。
单页应用（SPA）举措与原生桌面应用程序所使用的多文件接口（MDI）呈现技术类似。