首页 文章

单页应用:优缺点[关闭]

提问于
浏览
184

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

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

=== ADVANTAGES ===

1. SPA is extremely good for very responsive sites:

服务器端呈现很难为所有中间状态实现 - 小视图状态不能很好地映射到URL . 单页应用的区别在于它们能够重绘UI的任何部分而无需服务器往返来检索HTML . 这是通过具有处理数据的模型层和从模型读取的视图层将数据与数据表示分离来实现的 .

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

2. With SPA we don't need to use extra queries to the server to download pages.

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

3.May be any other advantages? Don't hear about any else..

=== DISADVANTAGES ===
  • 客户端必须启用javascript .

  • 只有一个网站入口点 .

  • 安全 .

P.S. 我've worked on SPA and non-SPA projects. And I'米问这些问题因为我需要加深理解 . 没有理由伤害SPA支持者 . 不要让我多读一些关于SPA的信息 . 我只是想听听你对此的考虑 .

11 回答

  • 133

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

    1. SPA is extremely good for very responsive sites:

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

    2. With SPA we don't need to use extra queries to the server to download pages.

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

    3. May be any other advantages? Don't hear about any else..

    • 这些天你可以放心地假设客户端将启用支持JavaScript的浏览器 .

    • 只有网站的一个入口点 . 正如我之前提到的,维护状态是可能的,你可以根据需要拥有任意数量的入口点,但你应该有一个肯定的 .

    • 即使在SPA用户中也只能看到他拥有的权利 . 你不必一次注入所有东西 . 加载diff html模板和javascript async也是SPA的有效部分 .

    Advantages that I can think of are:

    • 渲染html显然需要一些资源,现在每个访问你网站的用户都在这样做 . 此外,不仅渲染主要逻辑现在完成客户端而不是服务器端 .

    • 日期时间问题 - 我只是给客户端UTC时间是预设格式,甚至不关心我让javascript处理它的时区 . 这是我必须根据用户IP派生的位置猜测时区的巨大优势 .

    • 对我来说状态在SPA中得到了更好的维护,因为一旦你设置了变量,你就知道它会在那里 . 这给人一种开发应用程序而不是网页的感觉 . 这有助于制作像foodpanda,flipkart,amazon这样的网站 . 因为如果您没有使用客户端状态,那么您使用的是昂贵的会话 .

    • 网站肯定是非常敏感的 - 我将采取一个极端的例子来尝试在非SPA网站上制作计算器(我知道它很奇怪) .

    评论更新

    似乎没有人提到套接字和长轮询 . 如果您从另一个客户端注销移动应用程序,那么您的浏览器也应该注销 . 如果不使用SPA,则必须在每次重定向时重新创建套接字连接 . 这也应该适用于通知, Profiles 更新等数据的任何更新 . 另一个视角:除了您的网站,您的项目是否会涉及原生移动应用程序?如是,你最有可能从服务器(即JSON)向原生应用程序提供原始数据并进行客户端处理来呈现它,对吗?所以有了这个断言,你就是在做一个客户端渲染模型 . 现在问题变成了,为什么不应该为项目的网站版本使用相同的模型?有点不用脑子 . 然后问题就变成了您是否只想为SEO优势和可共享/可收藏的URL的便利性呈现服务器端页面

  • 2

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

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

    Advantages

    • 更简单的状态跟踪 - 无需使用cookie,表单提交,本地存储,会话存储等来记住2页加载之间的状态 .

    • 每个页面上的锅炉板内容(页眉,页脚,徽标,版权 Banner 等)仅为每个典型的浏览器会话加载一次 .

    • 切换"pages"时没有开销延迟 .

    Disadvantages

    • 性能监控 - 双手绑定:我见过的大多数浏览器级性能监控解决方案仅专注于页面加载时间,例如第一个字节的时间,构建DOM的时间,HTML的网络往返,onload事件等 . 更新通过AJAX加载页面无法测量 . 有一些解决方案可以让您检测代码以记录显式度量,例如单击链接,启动计时器,然后在呈现AJAX结果后结束计时器,并发送反馈 . 例如,New Relic支持此功能 . 通过使用SPA,您只能使用几种可能的工具 .

    • 安全/渗透测试 - 双手绑定:当SPA框架动态构建整个页面时,自动安全扫描可能难以发现链接 . 可能有解决方案,但同样,你自己也有限制 .

    • 捆绑:当您在初始页面加载时下载整个网站所需的所有代码时,很容易陷入这种情况,这对于低带宽连接可能会非常糟糕 . 你可以捆绑你的JavaScript和CSS文件,试着在你去的时候加载更自然的块,但是现在你需要维护那个映射并观察非预期的文件是否通过未实现的依赖关系(只是发生在我身上) . 再次,可解决,但成本 .

    • 大爆炸重构:如果你想做一个重大的架构改变,比如说,从一个框架切换到另一个框架,以最大限度地降低风险,它全部或全部都没有 . 如果要更改,则必须一次更改整个应用程序 .

    • 导航的复杂性:存在工具以帮助维护SPA中的导航上下文_t40214_ t需要其中任何一个 .

    • 搞清代码的复杂性:我们自然会将网站视为页面 . 多页面应用程序通常逐页分区,这有助于维护 .

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

  • 0

    缺点

    1. Client must enable javascript. 是的,这是SPA的明显劣势 . 在我的情况下,我知道我可以期望我的用户启用JavaScript . 如果你可以't then you can'吨做一个SPA,期间 . 这就像尝试将.NET应用程序部署到没有安装.NET Framework的计算机上 .

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

    3. Security. 此问题不是SPA独有的,当您拥有"old-school"客户端 - 服务器应用程序(使用超文本链接页面之间的HATEOAS模型)时,您必须以完全相同的方式处理安全性 . 它希望您的客户端能够访问所有代码,然后您必须将可下载的JavaScript拆分为单独的区域 . 我只是把它绑定到我的基于SammyJS的路由系统中,因此浏览器只根据用户角色的初始加载请求客户端知道它应该有权访问的内容,然后这就变成了无问题 . )

    优点

    • 在许多情况下,SPA(很少被提及)的主要架构优势是您的应用程序的"chattiness"大幅减少 . 如果你正确地设计它以处理客户端上的大多数处理(毕竟,整点),那么对服务器的请求数量(读取"possibilities for 503 errors that wreck your user experience")将大大减少 . 事实上,SPA可以完全实现离线处理,在某些情况下是巨大的 .

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

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

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

  • 28

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

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

    更新19.06.16:

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

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

  • 49

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

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

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

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

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

  • 39

    对于谷歌,亚马逊等公司,其服务器在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可用性,服务器端日志记录,安全性不再重要 .

  • 8

    2. With SPA we don't need to use extra queries to the server to download pages.

    我还需要学习很多,但自从我开始学习SPA以来,我就爱他们 .

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

    在许多不是SPA的Web应用程序中,您将看到它们仍将检索并向创建ajax请求的页面添加内容 . 所以我认为SPA超越了考虑:如果要检索和显示的内容会怎样使用ajax是整个页面?而不仅仅是页面的一小部分?

    让我介绍一个场景 . 考虑您有2页:

    • 包含产品列表的页面

    • 一页查看特定产品的详细信息

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

    • 获取带有产品详细信息的json对象的请求

    • 获取html模板的请求,其中将插入产品详细信息

    然后,客户端应用程序将数据插入到html模板中并显示它 .

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

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

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

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

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

  • 12

    Disadvantages :从技术上讲,SPA的设计和初步开发很复杂,可以避免 . 不使用此SPA的其他原因可能是:

    • a)安全性:由于跨站点脚本(XSS),单页应用程序与传统页面相比安全性较低 .

    • b)内存泄漏:JavaScript中的内存泄漏甚至会导致强大的计算机速度变慢 . 由于传统网站鼓励在页面之间导航,因此由前一页引起的任何内存泄漏几乎被清除,留下较少的残留物 .

    • c)客户端必须启用JavaScript才能运行SPA,但在多页面应用程序中,可以完全避免使用JavaScript .

    • d)SPA增长到最佳尺寸,导致等待时间长 . 例如:使用较慢的连接在Gmail上工作 .

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

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

  • 4

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

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

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

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

  • 2

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

    • 这会将会话(以及它的安全性)移到SPA上,从而减轻服务器的所有开销 .

    • 您的API变得既稳定又易于扩展 .

    暗示早些时候,但没有明确说明;如果您的目标是部署Android&Apple应用程序编写一个由本机调用包装的JavaScript SPA,以便在浏览器(Android或Apple)中托管屏幕,从而无需同时维护Apple代码库和Android代码库 .

  • 1

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

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

相关问题