单页应用:优缺点

时间:2014-02-18 18:12:54

标签: javascript architecture client-side single-page-application

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

问题: 您是否可以担任SPA的拥护者并证明我对前三个陈述有误?

                              === ADVANTAGES ===

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

  

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

     

单页应用程序的区别在于它们重绘任何部分的能力   UI而不需要服务器往返来检索HTML。这个   通过将数据与数据表示分开来实现   具有处理数据的模型层和读取的视图层   来自模特。

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

2。使用SPA,我们无需对服务器使用额外查询来下载页面。

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

3.可能还有其他优势吗?别忘了其他任何事情......

                            === DISADVANTAGES ===
  1. 客户端必须启用javascript。
  2. 该网站只有一个入口点。
  3. 安全。
  4. P.S。 我参与过SPA和非SPA项目。我问这些问题因为我需要加深理解。没有理由伤害SPA支持者。不要让我再读一些关于SPA的信息。我只是想听听你对此的考虑。

11 个答案:

答案 0 :(得分:140)

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

<强> 1。 SPA非常适合响应迅速的网站:

服务器端呈现并不像过去那样简单,例如在URL中保留#hash,或者最近HTML5 pushState。使用此方法,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网站上制作计算器(我知道它很奇怪)。
  5. 评论更新

      

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

         

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

答案 1 :(得分:56)

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

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

<强>优点

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

<强>缺点

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

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

答案 2 :(得分:39)

缺点

<强> 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的实时部署和版本一致性时,这会变得很有价值。)

  4. 所以,最重要的是:如果你需要离线处理(或者至少希望你的客户能够偶尔服务器中断) - 大大降低你自己的硬件成本 - 你可以假设JavaScript&amp;现代浏览器,那么你需要一个SPA。在其他情况下,这更多是权衡。

答案 3 :(得分:28)

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

在开发SPA时,您将被迫处理搜索引擎优化问题,可能是通过对所有网站进行后期渲染并创建静态html快照以供抓取工具使用。这将需要在适当的基础设施上进行可靠的投资。

更新19.06.16:

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

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

答案 4 :(得分:12)

我想让SPA成为数据驱动应用程序的最佳选择。 gmail当然是关于数据的,因此是SPA的一个很好的候选者。

但如果您的网页主要用于展示,例如服务条款页面,那么SPA就完全有点过分了。

我认为最好的地方是有一个混合了SPA和静态/ MVC风格页面的网站,具体取决于特定页面。

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

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

答案 5 :(得分:8)

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

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

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

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

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

答案 6 :(得分:4)

<强> 2。使用SPA,我们无需对服务器使用额外查询来下载页面。

我还需要学习很多但是自从我开始学习SPA之后,我就爱上它了。

这一点可能会产生巨大的差异。

在许多非SPA的网络应用中,您会看到他们仍会检索并向发出ajax请求的网页添加内容。所以我认为SPA超越了考虑:如果使用ajax检索和显示的内容是整个页面怎么办?而不仅仅是页面的一小部分?

让我介绍一个场景。考虑一下你有两页:

  1. 包含产品列表的页面
  2. 查看特定产品详情的页面
  3. 请考虑您在列表页面。然后单击产品以查看详细信息。客户端应用程序将触发2个ajax请求:

    1. 获取带有产品详细信息的json对象的请求
    2. 要求获取将插入产品详细信息的html模板
    3. 然后,客户端应用程序会将数据插入到html模板中并显示它。

      然后你回到列表(没有请求这个!)然后你打开另一个产品。这次,只有ajax请求才能获得产品的详细信息。 html模板将是相同的,因此您无需再次下载。

      您可能会说,在非SPA中,当您打开产品详细信息时,您只发出1个请求,在这种情况下我们做了2.是的。但是从整体的角度来看,当您浏览多个页面时,请求的数量会更少。而且客户端和服务器之间传输的数据也会降低,因为html模板将被重用。此外,您不需要在每个请求中下载所有页面中存在的所有css,图像,javascript文件。

      另外,让我们考虑您的服务器端语言是Java。如果你分析我提到的2个请求,1下载数据(你不需要加载任何视图文件并调用视图呈现引擎)和其他下载和静态html模板,这样你就可以拥有一个可以检索的HTTP Web服务器直接而不必调用Java应用程序服务器,不进行任何计算!

      最后,大公司正在使用SPA:Facebook,GMail,亚马逊。他们不玩,他们有最好的工程师研究这一切。因此,如果您没有看到您最初可以信任的优势,并希望在未来发现它们。

      但使用良好的SPA设计模式很重要。您可以使用AngularJS之类的框架。如果没有使用好的设计模式,请不要尝试实施SPA,因为最终可能会弄得一团糟。

答案 7 :(得分:2)

<强>缺点: 从技术上讲,SPA的设计和初步开发是复杂的,可以避免。不使用此SPA的其他原因可能是:

  • a)安全性:由于跨站点脚本(XSS),单页应用程序与传统页面相比安全性较低。
  • b)内存泄漏:JavaScript中的内存泄漏甚至会导致强大的计算机速度变慢。由于传统网站鼓励在页面之间导航,因此上一页所造成的任何内存泄漏几乎都会被清理干净,留下更少的残留物。
  • c)客户端必须启用JavaScript才能运行SPA,但在多页面应用程序中,可以完全避免使用JavaScript。
  • d)SPA增长到最佳尺寸,导致等待时间长。例如:使用较慢的连接处理Gmail。

除此之外,其他架构限制包括导航数据丢失,浏览器中没有导航历史记录以及使用硒进行自动功能测试的困难。

This链接解释单页应用程序的优点和缺点。

答案 8 :(得分:2)

在我的开发中,我发现使用SPA有两个明显的优势。这并不是说在传统的Web应用程序中无法实现以下功能,只是我看到增量收益而不会带来额外的缺点。

  • 可能会减少服务器请求,因为呈现新内容并不总是或甚至不是http服务器请求新的html页面。但我说有潜力,因为新内容很容易需要Ajax调用来提取数据,但数据可能比自身增加更多,加上标记提供净效益。

  • 维持“状态”的能力。简单来说,在应用程序的入口处设置一个变量,它将在整个用户体验中可用于其他组件,而不会传递它或将其设置为本地存储模式。然而,智能地管理这种能力是保持顶级范围整洁的关键。

除了要求JS(对于网络应用程序不是一件疯狂的事情)之外,我认为其他明显的缺点要么不是特定于SPA,要么可以通过良好的习惯和发展模式来缓解。

答案 9 :(得分:1)

在没有首先定义如何解决服务器端的安全性和API稳定性的情况下,尽量不要考虑使用SPA。然后,您将看到使用SPA的一些真正优势。具体来说,如果您使用实现OAUTH 2.0安全性的RESTful服务器,您将实现两个基本的关注点分离,从而降低开发和维护成本。

  1. 这会将会话(以及它的安全性)移到SPA上,从而减轻服务器的所有开销。
  2. 您的API变得既稳定又易于扩展。
  3. 早些时候暗示,但未明确;如果您的目标是部署Android&amp; Apple应用程序编写一个由本机调用包装的JavaScript SPA,以便在浏览器(Android或Apple)中托管屏幕,从而无需同时维护Apple代码库和Android代码库。

答案 10 :(得分:0)

我知道这是一个较旧的问题,但我想增加单页应用程序的另一个缺点:

如果构建一个以数据语言(如XML或JSON)而不是格式化语言(如HTML)返回结果的API,则可以实现更高的应用程序互操作性,例如,在企业对企业中(B2B) )应用程序。这种互操作性具有很大的好处,但允许人们编写软件来“挖掘”(或窃取)您的数据。这个特殊的缺点对于所有使用数据语言的API都是通用的,而不是一般的SPA(实际上,要求服务器提供预呈现的HTML的SPA可以避免这种情况,但代价是模型/视图分离不佳)。通过这种缺点暴露的这种风险可以通过各种手段来缓解,例如请求限制和连接阻塞等等。