单页面应用程序

单页应用程序

一个单页的应用程序SPA)是一个Web应用程序网站,一个单一的适合网页与提供的目标用户体验类似于的桌面应用程序。在SPA中,通过单个页面加载检索所有必需的代码(HTMLJavaScriptCSS)[1],或者根据需要动态加载适当的资源并将其添加到页面,通常是响应于用户操作。页面不会在进程中的任何一点重新加载,也不会将传输转移到另一个页面,尽管可以使用位置哈希HTML5 历史记录API来提供应用程序中单独的逻辑页面的感知和导航性。[2]与单页应用程序的交互通常涉及与Web服务器的幕后动态通信。

内容

历史编辑

术语单页应用的起源尚不清楚,尽管至少在2003年之前讨论了这个概念。[3] 斯图尔特(Stunix)莫里斯在四月份在slashdotslash.com上写了自己的网站,具有相同的目标和功能2002年44日,同一年,Lucas Birdeau,Kevin Hakman,Michael Peachey和Evan Yeh在美国专利8,136,109中描述了单页应用程序的实现。[5]

可以在Web浏览器中使用JavaScript来显示用户界面(UI),运行应用程序逻辑,并与Web服务器进行通信。成熟的开源库可用于支持SPA的构建,减少了开发人员编写的JavaScript代码的数量。

技术方法编辑

有各种可用的技术,即使应用程序需要服务器通信,浏览器也可以保留单个页面。

JavaScript框架编辑

Web浏览器JavaScript框架,如AngularJSEmber.jsMeteor.jsExtJSReact都采用了SPA原则。

  • AngularJS是一个完全的客户端框架。AngularJS的模板是基于双向UI数据绑定。数据绑定是每当模型更改时更新视图的自动方法,以及每当视图更改时更新模型。HTML模板在浏览器中编译。编译步骤创建纯HTML,浏览器重新呈现到实时视图中。为后续页面浏览重复该步骤。在传统的服务器端HTML编程中,诸如控制器和模型之类的概念在服务器进程中进行交互以产生新的HTML视图。在AngularJS框架中,控制器和模型状态保持在客户端浏览器中。因此,新页面能够在不与服务器进行任何交互的情况下生成。
  • Ember.js是基于模型视图 - 控制器(MVC)软件架构模式的客户端JavaScript Web应用程序框架。它允许开发人员通过将通用习语和最佳实践纳入框架来创建可扩展的单页面应用程序,该框架提供丰富的对象模型,声明性双向数据绑定,计算属性,由Handlebars.js提供的自动更新模板以及路由器用于管理应用状态。
  • Meteor.js是专为SPA设计的全栈(客户端 - 服务器)JavaScript框架。它具有比Angular,Ember或ReactJS更简单的数据绑定[6],并且使用分布式数据协议[7]发布订阅模式来实时地将数据更改传播到客户端,而不需要开发人员编写任何同步代码。全堆栈反应性确保从数据库到模板的所有图层在必要时自动更新。生态系统软件包如Server Side Rendering [8]解决了搜索引擎优化问题。
  • Aurelia是用于移动,桌面和网络的JavaScript客户端框架。它类似于AngularJS,但更新,更符合标准,并采用模块化方法。Aurelia是用下一代ECMAScript编写的
  • Vue.js Vue.js(通常称为Vue;发音/vjuː/,如视图)是一个用于构建用户界面的开源渐进JavaScript框架。通过其cli和webpack,我们可以轻松创建SPA。

Ajax编辑

目前使用的最突出的技术是Ajax[1]主要使用JavaScript中的XMLHttpRequest / ActiveX对象(不推荐使用)对象,其他Ajax方法包括使用IFRAME或脚本HTML元素。诸如jQuery之类的流行图书馆,使来自不同制造商的浏览器的Ajax行为标准化,进一步推广了Ajax技术。

Websockets编辑

WebSockets是HTML5规范中双向状态实时客户端 - 服务器通信技术的一部分,在性能方面优于Ajax [9]和简单性。

服务器发送的事件编辑

服务器发送事件(SSEs)是一种技术,服务器可以启动数据传输到浏览器客户端。一旦建立了初始连接,事件流将保持打开,直到客户端关闭。SSE通过传统的HTTP发送,并具有WebSockets缺乏设计的各种功能,如自动重新连接,事件ID以及发送任意事件的能力。[10]

浏览器插件编辑

尽管这种方法已经过时了,但也可以使用诸如SilverlightFlashJava applet之类的浏览器插件技术来实现对服务器的异步调用。

数据传输(XML,JSON和Ajax)编辑

对服务器的请求通常会导致原始数据(例如,XMLJSON)或新的HTML返回。在服务器返回HTML的情况下,客户端上的JavaScript会更新DOM的一部分区域(文档对象模型)。[11]当返回原始数据时,通常使用客户端JavaScript XML /(XSL)进程(在JSON的情况下为模板)将原始数据转换为HTML,然后将其用于更新部分区域的DOM。

服务器架构编辑

瘦服务器架构编辑

SPA将逻辑从服务器移动到客户端。这导致Web服务器发展成为纯数据API或Web服务的角色。在某些方面,这种体系结构的转变已经形成了“瘦客户机体系结构”,以突显出复杂性已经从服务器转移到客户端,而最终会降低系统整体的复杂性。

厚状态服务器架构编辑

服务器保持必要状态以记忆页面的客户端状态。以这种方式,当任何请求发送到服务器(通常是用户操作)时,服务器发送适当的HTML和/或JavaScript以及具体的更改,使客户端进入新的期望状态(通常是添加/删除/更新客户端DOM)。同时,更新服务器中的状态。大多数逻辑在服务器上执行,HTML通常也在服务器上呈现。在某些方面,服务器模拟Web浏览器,接收事件并执行服务器状态的增量更改,自动传播到客户端。

这种方法需要更多的服务器内存和服务器处理,但优点是简化的开发模式,因为a)应用程序通常在服务器中完全编码,并且b)服务器中的数据和UI状态在同一内存空间中共享,没有需要定制的客户端/服务器通信网桥。

厚无状态服务器架构编辑

这是有状态服务器方法的一个变体。客户端页面通常通过Ajax请求将表示其当前状态的数据发送到服务器。使用这些数据,服务器能够重构需要修改的页面部分的客户端状态,并可以生成必需的数据或代码(例如,作为JSON或JavaScript),返回给客户端它到一个新的状态,通常根据客户端动作来修改页面DOM树。

这种方法要求向服务器发送更多的数据,并且每个请求可能需要更多的计算资源来部分或全部地重构服务器中的客户端页面状态。同时,这种方法更容易扩展,因为在服务器中不存在每个客户端页面数据,因此,可以将Ajax请求分派到不同的服务器节点,而不需要会话数据共享或服务器关联。

本地运行编辑

一些SPA可以使用文件URI方案从本地文件执行。这使用户能够从服务器下载SPA,并从本地存储设备运行文件,而不依赖于服务器连接。如果这样的SPA想要存储和更新数据,它必须使用基于浏览器的Web存储。这些应用程序受益于HTML5提供的进步。[12]

编辑的SPA模式的挑战

因为SPA是远离原本设计的浏览器的无状态页面重绘模型的演进,出现了一些新的挑战。每个这些问题都有一个有效的解决方案[13]

  • 客户端JavaScript库解决各种问题。
  • 专门针对SPA模型的服务器端Web框架。[14] [15] [16]
  • 浏览器的演变和为SPA模式设计的HTML5规范。[17]

搜索引擎优化编辑

由于在一些流行的Web搜索引擎的爬虫上缺乏JavaScript执行,[18] SEO(搜索引擎优化)历来对于希望采用SPA模型的公众网站提出了一个问题。[19]

在2009年至2015年期间,Google网站管理员中心提出,然后推荐使用“AJAX爬行方案” [20] [21]在状态AJAX页面(#!)的片段标识符中使用初始感叹号。SPA站点必须执行特殊行为,以便搜索引擎的抓取工具提取相关元数据。对于不支持此URL哈希方案的搜索引擎,SPA的散列网址不可见。这些“hash-bang”URI被W3C的许多作者,包括Jeni Tennison都认为是有问题的,因为它们使浏览器中没有JavaScript被激活的页面无法访问。当浏览器不允许在Referer头文件中发送片段标识符时,它们也会中断HTTP引用头。[22]在2015年,Google弃用了他们的hash-bang AJAX抓取方案。[23]

或者,应用程序可能使服务器上的第一页加载和客户端上的后续页面更新。这在传统上是困难的,因为渲染代码可能需要在服务器和客户端中以不同的语言或框架编写。使用无逻辑模板,从一种语言到另一种语言的交叉编译,或在服务器和客户端上使用相同的语言可能有助于增加可共享的代码量。

由于SEA兼容性在SPA中不是微不足道的,因此值得注意的是,在搜索引擎索引是要求或需求的上下文中,通常不使用SPA。用例包括隐藏认证系统后面的私有数据的应用程序。在这些应用程序是消费产品的情况下,通常将经典的“页面重绘”模型用于应用程序着陆页和营销网站,该站点为应用程序提供足够的元数据,以便在搜索引擎查询中显示为匹配项。博客,支持论坛和其他传统的页面重绘文物通常位于SPA周围,可以将搜索引擎与相关术语进行种子关联。

以服务器为中心的Web框架(如基于Java的ItsNat)使用的另一种方法是使用相同的语言和模板技术在服务器上呈现任何超文本。在这种方法中,服务器精确地知道客户端上的DOM状态,在服务器中生成所需的任何大或小的页面更新,并通过Ajax传输确切的JavaScript代码,使客户端页面进入执行DOM方法的新状态。开发人员可以决定哪些页面状态必须由网络蜘蛛抓取SEO,并且能够在加载时生成必需的状态,生成纯HTML而不是JavaScript。在ItsNat框架的情况下,这是自动的,因为ItsNat将客户端DOM树作为Java W3C DOM树保留在服务器中; 在服务器中渲染此DOM树将在加载时生成纯HTML,并为Ajax请求生成JavaScript DOM操作。这种双重性对于SEO来说非常重要,因为开发人员可以使用相同的Java代码和基于纯HTML的模板来构建服务器中所需的DOM状态; 在页面加载时,传统的HTML由ItsNat生成,使DOM状态与SEO兼容。从版本1.3开始, [24] ItsNat提供了一种新的无状态模式,并且客户端DOM不保留在服务器上,因为在处理任何基于Ajax的Ajax请求时,使用无状态模式客户机在服务器上部分或全部重建DOM状态由客户端发送的所需数据通知服务器当前的DOM状态;

有几个解决方法,使它看起来像网站是可抓取的。两者都涉及创建单独的HTML页面来镜像SPA的内容。服务器可以创建一个基于HTML的站点版本,并将其提供给爬网程序,或者可以使用无头浏览器(如PhantomJS)来运行JavaScript应用程序并输出生成的HTML。

这两个都需要相当多的努力,最终可能会给大型复杂网站带来维护头痛。还有潜在的SEO陷阱。如果服务器生成的HTML被认为与SPA内容有太大的不同,那么该站点将被处罚。运行PhantomJS以输出HTML可能会减慢页面的响应速度,这对于搜索引擎(特别是谷歌)来降低排名。[25]

客户端/服务器代码分区编辑

增加服务器和客户端之间可共享的代码量的一种方法是使用无逻辑的模板语言(如MustacheHandlebars)。这样的模板可以从不同的主机语言呈现,例如服务器上的Ruby和客户端中的JavaScript。然而,仅仅共享模板通常需要重复的业务逻辑,用于选择正确的模板并用数据填充它们。仅在更新页面的一小部分时(例如大型模板中的文本输入的值),从模板渲染可能会产生负面的效果。更换整个模板也可能会干扰用户的选择或光标位置,只能更改更改的值。

浏览器历史编辑

根据定义“SPA”,该模型使用“前进/后退”按钮打破了浏览器的页面历史记录导航设计。当用户按下返回按钮,期望SPA内的先前屏幕状态,而是应用程序的单页面卸载和浏览器历史记录中的前一页面时,会呈现可用性障碍。

用于SPA的传统解决方案是根据当前屏幕状态来更改浏览器URL的散列片段标识符。这可以通过JavaScript实现,并导致在浏览器中构建URL历史记录事件。只要SPA能够从包含在URL散列中的信息复原相同的屏幕状态,则保留预期的后退按钮行为。

为了进一步解决这个问题,HTML5规范引入了pushStatereplaceState,为实际的URL和浏览器历史提供了编程访问。

分析编辑

Analytics(分析)工具(如Google Analytics(分析))在很大程度上依赖于浏览器中加载的全新页面,由新的页面加载启动。SPAs不能这样工作。

第一页加载后,所有后续页面和内容更改都由应用程序内部处理,应用程序只需调用功能来更新分析包。无法调用所述功能,浏览器不会触发新的页面加载,任何内容都不会添加到浏览器历史记录中,而分析软件包不知道在做什么。

将页面加载添加到SPA编辑

可以使用HTML5历史记录API将页面加载事件添加到SPA中; 这将有助于整合分析。困难在于管理这一点,并确保正确跟踪所有内容 - 这涉及检查丢失的报告和双重条目。一些框架为大多数主要分析提供商提供开源分析集成。开发人员可以将它们整合到应用程序中,并确保所有内容都正常运行,但是从头开始无需做任何事情。[25]

初始加载速度编辑

单页应用程序比基于服务器的应用程序的首页加载速度较慢。这是因为在浏览器中将所需的视图呈现为HTML之前,必须先卸载框架和应用程序代码。基于服务器的应用程序只需将所需的HTML推送到浏览器,减少延迟和下载时间。

加快页面加载编辑

有一些方法可以加快SPA的初始加载,例如在需要时缓存和延迟加载模块的重要方法。但是,不可能避免需要下载框架,至少有一些应用程序代码,并且很有可能在浏览器中显示某些内容之前触发数据的API。[25]这是一个“现在付钱,或者稍后付钱”的权衡。性能和等待时间的问题仍然是开发人员必须做出的决定。

页面生命周期编辑

在初始页面加载中完全加载SPA,然后根据需要从服务器加载的新页面片段替换或更新页面区域。为了避免过度下载未使用的功能,SPA将经常逐渐下载更多的功能,因为它们是必需的,页面的小碎片或完整的屏幕模块。

这样一来,SPA中的“状态”和传统网站中的“页面”之间就存在类比。因为同一页面中的“状态导航”类似于页面导航,理论上,任何基于页面的网站都可以在同一页面中转换为单页替换,仅将比较非SPA中的连续页面的更改的部分结果。

网络上的SPA方法类似于本地桌面应用程序中流行的单文档界面(SDI)演示技术。

参考编辑

  1. b Flanagan,David,“JavaScript - The Definitive Guide”,5th ed。,O'Reilly,Sebastopol,CA,2006,p.497
  2. “修复后退按钮:使用位置哈希的SPA行为”沙拉三明治软件博客。检索2016年1月18日
  3. “内浏览:扩展网页浏览导航范式” 。检索2011-02-03
  4. “Slashdotslash.com:使用DHTML的自包含的网站” 。检索2012-07-06
  5. “美国专利8,136,109” 。检索2002-04-12
  6. “流星火焰”Meteor Blaze是一个用于创建实时更新用户界面的强大库。Blaze具有与Angular,Backbone,Ember,React,Polymer或Knockout相同的目的,但使用起来更加容易。我们建立它是因为我们认为其他库使用户界面编程不必要地困难和困惑。
  7. ^ DDP介绍,2012年3月21日
  8. “流星服务器端渲染” 。检索31日年1月到2015年
  9. “使用AJAX和WebSockets实时监控”www.computer.org 。检索2016年6月1日
  10. “服务器发送的事件”。W3C。2013年7月17日
  11. “使用InnerHTML”www.webrocketx.com 。检索2016年1月21日
  12. “未主机的网络应用程序”
  13. “单页面接口宣言” 。检索2014-04-25
  14. “德比” 。检索2011-12-11
  15. “Sails.js” 。检索2013-02-20
  16. “教程:单页面接口网站WithNat” 。检索2011-01-13
  17. ^ HTML5
  18. “用户看到什么,抓取工具看到什么” 。检索2014 年1月6浏览器可以执行JavaScript并生成内容 - 爬网程序不能
  19. “使Ajax应用程序可追溯” 。检索2014 年1月6历史上,Ajax应用程序对于搜索引擎来说很难处理,因为Ajax内容的生成
  20. “AJAX可抓取的提案”。谷歌。2009年10月7日。检索2011 年7月13
  21. “(规格)使AJAX应用程序可追溯”。Google 。检索2013 年3月4
  22. “哈希URI”W3C博客。5月12日。检索2011 年7月13
  23. “弃用我们的AJAX抓取方案”官方Google网站管理员中心博客。检索2017-02-23
  24. “ItsNat v1.3发行说明” 。检索2013-06-09
  25. c Holmes,Simone(2015)。获得与Mongo,Express,Angular和Node的平均值。曼宁出版社。ISBN 978-1-6172-9203-3


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值