单页应用:优缺点

VB_*_*VB_ 199 javascript architecture client-side single-page-application

我读过SPA及其优点.我发现他们中的大多数都不能令人信服.有三个优点引起了我的怀疑.

问题: 你能否作为SPA的拥护者并证明我对前三个陈述有误?

                              === ADVANTAGES ===
Run Code Online (Sandbox Code Playgroud)

1. SPA非常适合响应迅速的网站:

服务器端呈现很难为所有中间状态实现 - 小视图状态不能很好地映射到URL.

单页应用程序的区别在于它们能够重绘UI的任何部分而无需服务器往返来检索HTML.这是通过具有处理数据的模型层和从模型读取的视图层将数据与数据表示分离来实现的.

为非SPA持有模型层有什么问题?SPA是客户端唯一与MVC兼容的架构吗?

2.使用SPA,我们不需要对服务器使用额外的查询来下载页面.

哈,用户在访问您的网站时可以下载多少页?二三?相反,出现了另一个安全问题,您需要将登录页面,管理页面等分成单独的页面.反过来,它与SPA架构发生冲突.

3.可能还有其他优势吗?不要听到任何其他..

                            === DISADVANTAGES ===
Run Code Online (Sandbox Code Playgroud)
  1. 客户端必须启用javascript.
  2. 只有一个网站入口点.
  3. 安全.

PS我曾参与SPA和非SPA项目.我问这些问题因为我需要加深理解.没有理由伤害SPA支持者.不要让我再读一些关于SPA的信息.我只是想听听你对此的考虑.

Par*_*rma 143

让我们来看看最受欢迎的SPA网站之一,GMail.

1. SPA非常适合响应迅速的网站:

服务器端渲染并不像以前那样简单,只需要在URL中保留#hash,或者最近使用HTML5pushState.使用此方法,Web应用程序的确切状态将嵌入页面URL中.与GMail一样,每次打开邮件时都会在URL中添加一个特殊的哈希标记.如果复制并粘贴到其他浏览器窗口,则可以打开完全相同的邮件(前提是他们可以进行身份​​验证).这种方法直接映射到更传统的查询字符串,区别仅在于执行.使用HTML5 pushState(),您可以消除#hash并使用完全经典的URL,这些URL可以在第一个请求时在服务器上解析,然后通过ajax在后续请求中加载.

2.使用SPA,我们不需要对服务器使用额外的查询来下载页面.

用户在访问我的网站时下载的页数?当他/她打开他/她的邮件帐户时,有多少邮件会被读取.我一口气读了> 50.现在邮件的结构几乎是一样的.如果您将使用服务器端呈现方案,则服务器将在每个请求(典型情况)上呈现它. - 安全问题 - 您应该/不应该为管理员/登录保留单独的页面,这完全取决于您的网站结构,例如,制作网站SPA并不意味着您打开所有的所有端点用户我的意思是我在我的spa网站上使用表单auth. - 在可能最常用的SPA框架Angular JS中,dev可以从网站加载整个html模板,以便可以根据用户身份验证级别来完成.为所有auth类型预加载html不是SPA.

3.可能还有其他任何优势吗?不要听到任何其他..

  • 这些天你可以放心地假设客户端将启用支持JavaScript的浏览器.
  • 只有一个网站的入口点.正如我之前提到的,维护状态是可能的,你可以根据需要设置任意数量的入口点,但你应该有一个肯定的.
  • 即使在SPA用户中,也只能看到他拥有的权利.你不必一次注入所有东西.加载diff html模板和javascript async也是SPA的有效部分.

我能想到的优点是:

  1. 渲染html显然需要一些资源,现在每个访问你网站的用户都在这样做.现在不仅渲染主要逻辑,而是在客户端而不是服务器端完成.
  2. 日期时间问题 - 我只是给客户端UTC时间是一个预先设置的格式,甚至不关心我让javascript处理它的时区.这是我必须根据从用户IP派生的位置猜测时区的巨大优势.
  3. 对我来说状态在SPA中得到了更好的维护,因为一旦你设置了变量,你就会知道它会在那里.这给人一种开发应用程序而不是网页的感觉.这有助于制作像foodpanda,flipkart,amazon这样的网站.因为如果您没有使用客户端状态,则使用昂贵的会话.
  4. 网站肯定是非常敏感的 - 我会举一个极端的例子来尝试在非SPA网站上制作一个计算器(我知道它很奇怪).

评论更新

似乎没有人提到插座和长轮询.如果您从另一个客户端注销移动应用程序,那么您的浏览器也应该注销.如果不使用SPA,则必须在每次重定向时重新创建套接字连接.这也应该适用于通知,配置文件更新等数据的任何更新

另一种观点:除了您的网站,您的项目是否会涉及原生移动应用程序?如果是,您很可能会从服务器(即JSON)向原始应用程序提供原始数据并进行客户端处理以呈现它,对吗?所以有了这个断言,你就是在做一个客户端渲染模型.现在问题变成了,为什么不应该为项目的网站版本使用相同的模型?有点不用脑子.然后问题就变成了您是否只想为SEO优势和可共享/可收藏的URL的便利性呈现服务器端页面

  • 擅长制作这个社区Wiki答案:)这些都很棒 (4认同)
  • 您无法使用SPA轻松索引SEO优化页面. (4认同)
  • 似乎没有人提到插座和长轮询.如果您从另一个客户端注销移动应用程序,那么您的浏览器也应该注销.如果不使用SPA,则必须在每次重定向时重新创建套接字连接.这也应该适用于通知,个人资料更新等数据的任何更新. (3认同)
  • @ Ankit_Shah55这可能不再适用(至少谷歌,无论如何拥有大部分搜索引擎市场份额).请参阅Google的"弃用我们的AJAX抓取方案".我的理解是,您不必为Google做任何特殊的事情来索引您的SPA.我认为你需要确保支持pushstate,但是,因为我不认为google索引哈希片段. (2认同)

Bra*_*don 62

我是一个实用主义者,所以我会尝试从成本和收益的角度来看待这个问题.

请注意,对于我给出的任何缺点,我都认识到它们是可以解决的.这就是为什么我不把任何东西视为黑白,而是成本和收益.

好处

  • 更轻松的状态跟踪 - 无需使用cookie,表单提交,本地存储,会话存储等来记住2页加载之间的状态.
  • 每个页面上的锅炉板内容(页眉,页脚,徽标,版权横幅等)仅在每个典型的浏览器会话中加载一次.
  • 切换"页面"时没有开销延迟.

缺点

  • 性能监控 - 双手绑定:我见过的大多数浏览器级性能监控解决方案仅专注于页面加载时间,例如第一个字节的时间,构建DOM的时间,HTML的网络往返,onload事件等.更新页面通过AJAX进行后载不会被测量.有一些解决方案可以让您检测代码以记录显式度量,例如单击链接,启动计时器,然后在呈现AJAX结果后结束计时器,并发送反馈.例如,New Relic支持此功能.通过使用SPA,您只能使用几种可能的工具.
  • 安全/渗透测试 - 双手绑定:当SPA框架动态构建整个页面时,自动安全扫描很难发现链接.可能有解决方案,但同样,你限制了自己.
  • 捆绑:当您在初始页面加载时下载整个网站所需的所有代码时很容易陷入困境,这对于低带宽连接可能会非常糟糕.您可以捆绑您的JavaScript和CSS文件,以尝试加载更自然的块,但现在您需要维护该映射并观察非预期的文件是否通过未实现的依赖项(仅仅发生在我身上).再次,可解决,但成本.
  • 大爆炸重构:如果你想进行一次重大的架构改变,比如说,从一个框架切换到另一个框架,为了最大限度地降低风险,最好进行渐进式更改.也就是说,开始使用新的,在某些基础上迁移,如每页,每个功能等,然后删除旧的.使用传统的多页面应用程序,您可以将一个页面从Angular切换到React,然后在下一个sprint中切换另一个页面.有了SPA,它就是全有或全无.如果要更改,则必须一次更改整个应用程序.
  • 导航的复杂性:工具存在以帮助维护SPA中的导航上下文,例如history.js,Angular 2,其中大多数依赖于URL框架(#)或较新的历史API.如果每个页面都是单独的页面,则不需要任何页面.
  • 找出代码的复杂性:我们自然会将网站视为页面.多页面应用程序通常逐页分区,这有助于维护.

我再次认识到,这些问题中的每一个都是可以解决的,需要付出一定的代价.但是有一点,你花费所有的时间来解决你本来可以避免的问题.它回归了它们的好处和重要性.

  • 我从这个答案中得到的是,如果您正在做任何甚至非常认真的事情,请避免使用SPA。 (3认同)
  • 我认为这个回复提供了非常有效的反馈,他们实际上已经构建了一个大型复杂系统,并且经历了SPA带来的长期伤亡(或者看起来像这样) (2认同)
  • 我同意.当我们做概念验证时,SPA看起来很棒.现在3年后,我们已经看到了这个答案中提到的每个问题,我们仍然花费大量时间来尝试解决它们.框架更改不再是一个选项,我们坚持使用基本上停止开发的框架. (2认同)

Lar*_*ann 42

缺点

1.客户端必须启用javascript.是的,这是SPA的明显劣势.在我的情况下,我知道我可以期望我的用户启用JavaScript.如果你不能那么你不能做SPA,期间.这就像尝试将.NET应用程序部署到没有安装.NET Framework的计算机上.

2.只有一个入口点.我用 SammyJS解决了这个问题.2-3天的工作可以正确设置您的路由,人们将能够在您的应用中创建正确运行的深层链接书签.您的服务器只需要公开一个端点 - "给我这个应用程序的HTML + CSS + JS"端点(将其视为预编译应用程序的下载/更新位置) - 您编写的客户端JavaScript将处理实际进入应用程序.

3.安全.这个问题不是SPA独有的,当你有一个"老派"客户端 - 服务器应用程序(使用超文本链接页面之间的HATEOAS模型)时,你必须以完全相同的方式处理安全性.只是用户正在发出请求而不是您的JavaScript,结果是HTML而不是JSON或某种数据格式.在非SPA应用程序中,您必须保护服务器上的各个页面,而在SPA应用程序中,您必须保护数据端点.(而且,如果您不希望您的客户端访问所有代码,那么您必须将可下载的JavaScript拆分为不同的区域.我只是将其绑定到基于SammyJS的路由系统中,以便浏览器只请求根据用户角色的初始加载,客户端知道它应该有权访问的内容,然后这就成了一个问题.)

好处

  1. 在许多情况下,SPA(很少被提及)的主要架构优势是大大减少了应用程序的"烦躁感".如果您正确地设计它来处理客户端上的大多数处理(毕竟,整点),那么对服务器的请求数量(读取"可能导致用户体验破坏的503错误")将大大减少.实际上,SPA可以完成离线处理,这在某些情况下是巨大的.

  2. 如果你做得对,那么客户端渲染的性能肯定会更好,但这并不是构建SPA的最有说服力的理由.(毕竟,网络速度正在提高.)不要仅仅在此基础上为SPA提供案例.

  3. UI设计的灵活性可能是我发现的另一个主要优势.一旦我定义了我的API(使用JavaScript中的SDK),除了一些静态资源文件之外,我能够完全重写我的前端,对服务器没有任何影响.尝试使用传统的MVC应用程序!:)(当您需要担心API的实时部署和版本一致性时,这会变得很有价值.)

因此,底线:如果您需要离线处理(或者至少希望您的客户能够偶尔服务器中断) - 大大降低您自己的硬件成本 - 并且您可以假设JavaScript和现代浏览器,那么您需要SPA.在其他情况下,它更多的是权衡.

  • 另一个优点是SPA可以在iOS上保存为书签("添加到主屏幕"),并以全屏模式打开(假设您已经定义了正确的[meta tag](https://developer.apple.com) /library/safari/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html)),让它感觉像是原生应用而不是网页. (6认同)
  • 3.在传统的MVC应用程序中也很简单.如果您使用相同的数据进行操作,则只需在应用的V(视图)部分进行更改即可.这通常是模板,css和js. (6认同)
  • 我见过的大多数SPA应用程序都比服务器端应用程序更健谈.而不是单个请求获取数据,最终每页向服务器发出更多请求. (4认同)

Ill*_*dan 28

SPA的一个主要缺点 - SEO.直到最近Google和Bing才开始通过在抓取过程中执行JavaScript来索引基于Ajax的页面,并且在很多情况下,页面的索引编制不正确.

在开发SPA时,您将被迫处理SEO问题,可能是通过对所有站点进行后期渲染并创建静态html快照以供爬虫使用.这需要在适当的基础设施上进行可靠的投资.

更新19.06.16:

自从不久前写这个答案以来,我在单页应用程序(即AngularJS 1.x)上获得了更多的经验 - 所以我有更多的信息要分享.

在我看来,SPA应用程序的主要缺点是SEO,使它们仅限于那种"仪表板"应用程序.此外,与传统解决方案相比,您将在缓存方面遇到更多困难.例如,在ASP.NET中,缓存非常简单 - 只需启用OutputCaching就可以了:整个HTML页面将根据URL(或任何其他参数)进行缓存.但是,在SPA中,您需要自己处理缓存(通过使用某些解决方案,如二级缓存,模板缓存等).


Gre*_*Gum 12

我想说明SPA最适合数据驱动应用程序.gmail当然是关于数据的,因此是SPA的一个很好的候选者.

但是,如果您的页面主要用于显示,例如,服务条款页面,则SPA完全是过度杀伤.

我认为最佳位置是具有SPA和静态/ MVC样式页面混合的站点,具体取决于特定页面.

例如,在我正在构建的一个站点上,用户登陆标准MVC索引页面.但是当他们进入实际应用程序时,它会调用SPA.另一个优点是SPA的加载时间不在主页上,而是在应用页面上.主页上的加载时间可能会分散第一次站点用户的注意力.

这种情况有点像使用Flash.经过几年的经验,由于负载因素,仅Flash站点的数量降至接近零.但作为页面组件,它仍在使用中.


Val*_*itz 8

对于谷歌,亚马逊等公司,其服务器在24/7模式下以最大容量运行,减少流量意味着真正的金钱 - 更少的硬件,更少的能源,更少的维护.将CPU使用从服务器转移到客户端会带来回报,而SPA则会大放异彩.迄今为止优势超重的优点.因此,SPA或非SPA很大程度上取决于用例.

仅仅提到另一个,可能不那么明显(对于Web开发人员)用例的SPA:我目前正在寻找一种在嵌入式系统中实现GUI的方法,而基于浏览器的架构似乎对我很有吸引力.传统上,嵌入式系统中的UI可能性不大 - Java,Qt,wx等,或者是专有的商业框架.几年前,Adobe试图用闪存进入市场,但似乎并不那么成功.

如今,由于"嵌入式系统"在几年前与大型机一样强大,基于浏览器的UI通过REST连接到控制单元是一种可能的解决方案.优点是,UI的大量工具可以免费使用.(例如,Qt要求每个销售单位20-30美元的特许权使用费加上每个开发商3000-4000美元)

对于这样的体系结构,SPA提供了许多优点 - 例如,对于桌面应用程序开发人员更熟悉的开发方法,减少了服务器访问(通常在汽车行业中,UI和系统混乱是单独的硬件,其中系统部件具有RT OS).

由于唯一的客户端是内置浏览器,所以提到的缺点,如JS可用性,服务器端日志记录,安全性不再重要.