提问人:VB_ 提问时间:2/19/2014 最后编辑:VB_ 更新时间:12/13/2017 访问量:154189
单页应用程序:优点和缺点 [已关闭]
Single Page Application: advantages and disadvantages [closed]
问:
我读过关于SPA及其优势的文章。我发现他们中的大多数都没有说服力。有 3 个优点引起了我的怀疑。
问题:你能作为SPA的拥护者,证明我对前三个陈述是错误的吗?
=== ADVANTAGES ===
1. SPA 非常适合响应速度非常快的网站:
服务器端渲染很难实现所有中间体 状态 - 小视图状态不能很好地映射到 URL。
单页应用程序的特点是它们能够重绘任何部分 的 UI,而无需服务器往返来检索 HTML。这 通过将数据与数据的呈现方式分开来实现 具有处理数据的模型层和读取 从模型。
为非 SPA 保留模型层有什么问题?SPA 是否是客户端唯一与 MVC 兼容的体系结构?
2. 使用 SPA,我们不需要使用额外的查询来下载页面。
呵呵,用户在访问您的网站时可以下载多少页面?二、三?相反,出现了另一个安全问题,您需要将登录页面,管理页面等分开到单独的页面中。反过来,它与 SPA 体系结构冲突。
3.可能还有其他优势吗?别的都没听说过。.
=== DISADVANTAGES ===
- 客户端必须启用 javascript。
- 站点只有一个入口点。
- 安全。
附言我从事过 SPA 和非 SPA 项目。我之所以问这些问题,是因为我需要加深我的理解。没有伤害SPA支持者的意思。不要让我多读一点关于SPA的信息。我只是想听听你对此的看法。
答:
让我们看看最受欢迎的 SPA 网站之一 GMail。
1. SPA 非常适合响应速度非常快的网站:
服务器端渲染并不像以前那样困难,使用简单的技术,例如在 URL 中保留 #hash,或者最近的 HTML5 pushState
。使用此方法时,Web 应用的确切状态将嵌入到页面 URL 中。与 GMail 一样,每次打开邮件时,都会在 URL 中添加一个特殊的哈希标签。如果复制并粘贴到其他浏览器窗口可以打开完全相同的邮件(前提是它们可以进行身份验证)。这种方法直接映射到更传统的查询字符串,区别仅在于执行。使用 HTML5 pushState(),您可以消除并使用完全经典的 URL,这些 URL 可以在第一个请求时在服务器上解析,然后在后续请求中通过 ajax 加载。#hash
2. 使用 SPA,我们不需要使用额外的查询来下载页面。
用户在访问我的网站期间下载的页面数??当他/她打开他/她的邮件帐户时,他/她阅读了多少封邮件。我一口气读了 50 >。现在邮件的结构几乎相同。如果您将使用服务器端渲染方案,则服务器将在每个请求(典型情况下)渲染它。 - 安全问题 - 您应该/不应该为管理员/登录保留单独的页面,这完全取决于您的网站结构,例如 paytm.com 例如,制作一个网站 SPA 并不意味着您为所有用户打开所有端点,我的意思是我在我的 spa 网站上使用表单身份验证。 - 在可能最常用的 SPA 框架 Angular JS 中,开发人员可以从 Web 站点加载整个 html temple,因此可以根据用户的身份验证级别来完成。预加载所有身份验证类型的 html 不是 SPA。
3. 可能还有其他优势吗?别的都没听说过。.
- 如今,您可以放心地假设客户端将具有支持 JavaScript 的浏览器。
- 网站只有一个入口点。正如我之前提到的,可以维护状态,您可以根据需要拥有任意数量的入口点,但您肯定应该有一个。
- 即使在 SPA 中,用户也只能看到他拥有适当的权利。您不必一次注入所有东西。加载 diff html 模板和 javascript 异步也是 SPA 的有效部分。
我能想到的优点是:
- 渲染 HTML 显然需要一些资源,现在每个访问您网站的用户都在这样做。此外,不仅渲染,主要逻辑现在都是在客户端而不是服务器端完成的。
- 日期时间问题 - 我只是给客户端 UTC 时间是预设格式,甚至不关心我让 javascript 处理的时区。对于我必须根据从用户 IP 得出的位置来猜测时区来说,这是一个很大的优势。
- 对我来说,状态在SPA中维护得更好,因为一旦你设置了一个变量,你就知道它会在那里。这给人一种开发应用程序而不是网页的感觉。这通常对制作 foodpanda、flipkart、亚马逊等网站有很大帮助。因为如果不使用客户端状态,则使用的是昂贵的会话。
- 网站肯定反应灵敏 - 我将举一个极端的例子,尝试在非 SPA 网站中制作计算器(我知道它很奇怪)。
来自评论的更新
似乎没有人提到套接字和长轮询。 如果您从另一个客户端注销,比如移动应用程序,那么您的浏览器 也应该注销。如果不使用 SPA,则必须重新创建 套接字连接,每次有重定向。这也应该 处理数据中的任何更新,如通知、配置文件更新等
另一种观点:除了你的网站,你的项目也会 涉及原生移动应用程序?如果是,你很可能会 将原始数据从服务器(即 JSON)馈送到该本机应用程序,然后执行 客户端处理来呈现它,对吗?所以有了这个断言, 您已经在做客户端渲染模型了。现在的问题是 变成,为什么你不应该对网站版本使用相同的模型 您的项目?有点不费吹灰之力。那么问题就变成了 是否只想为了 SEO 的好处而呈现服务器端页面,以及 可共享/可书签 URL 的便利性
评论
弊
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 的路由系统中,这样浏览器就会根据用户角色的初始加载,只请求客户端知道它应该有权访问的内容,然后这就不再是问题了。
优势
在许多情况下,SPA 的一个主要架构优势(很少被提及)是大大减少了应用程序的“聊天性”。如果正确设计它以处理客户端上的大多数处理(毕竟是重点),那么对服务器的请求数量(阅读“破坏用户体验的 503 错误的可能性”)会大大减少。事实上,SPA 可以进行完全离线处理,这在某些情况下是巨大的。
如果做得好,客户端渲染的性能肯定会更好,但这并不是构建 SPA 的最令人信服的理由。(毕竟,网络速度正在提高。不要仅凭这一点来证明 SPA 的理由。
UI设计的灵活性也许是我发现的另一个主要优势。一旦我定义了我的 API(使用 JavaScript 中的 SDK),除了一些静态资源文件之外,我能够完全重写我的前端,对服务器的影响为零。尝试使用传统的 MVC 应用程序来做到这一点!:)(当您需要担心 API 的实时部署和版本一致性时,这将变得很有价值。
所以,底线:如果你需要离线处理(或者至少希望你的客户端能够在偶尔的服务器中断中幸存下来)——大大降低你自己的硬件成本——你可以假设JavaScript和现代浏览器,那么你需要一个SPA。在其他情况下,这更像是一种权衡。
评论
缺点: 从技术上讲,SPA的设计和初始开发是复杂的,可以避免。不使用此 SPA 的其他原因可能是:
- a) 安全性:由于跨站点脚本 (XSS),与传统页面相比,单页应用程序的安全性较低。
- b) 内存泄漏:JavaScript 中的内存泄漏甚至会导致功能强大的计算机速度变慢。由于传统网站鼓励在页面之间导航,因此由上一页引起的任何内存泄漏几乎都会被清除,留下更少的残留物。
- c) 客户端必须启用 JavaScript 才能运行 SPA,但在多页应用程序中可以完全避免 JavaScript。
- d) SPA生长到最佳大小,导致等待时间长。例如:在连接速度较慢的 Gmail 上工作。
除此之外,其他架构限制包括导航数据丢失、浏览器中没有导航历史记录日志以及使用 selenium 进行自动功能测试的困难。
此链接解释了单页应用程序的优点和缺点。
评论
对于谷歌、亚马逊等公司来说,他们的服务器在 24/7 模式下以最大容量运行,减少流量意味着真金白银——更少的硬件、更少的能源、更少的维护。将 CPU 使用率从服务器转移到客户端是有回报的,SPA 大放异彩。到目前为止,优点超过了缺点。 因此,SPA 与否 SPA 很大程度上取决于用例。
仅举一提另一个可能不那么明显的 SPA 用例(对于 Web 开发人员而言): 我目前正在寻找一种在嵌入式系统中实现 GUI 的方法,而基于浏览器的架构似乎对我很有吸引力。传统上,嵌入式系统中的UI可能性并不多 - Java,Qt,wx等或专有的商业框架。几年前,Adobe试图用flash进入市场,但似乎并不那么成功。
如今,由于“嵌入式系统”与几年前的大型机一样强大,因此通过REST连接到控制单元的基于浏览器的UI是一种可能的解决方案。优点是,免费提供大量的UI工具。(例如,Qt要求每个售出单位的特许权使用费为20-30美元,加上每个开发人员3000-4000美元)
对于这样的架构,SPA 提供了许多优势 - 例如,桌面应用程序开发人员更熟悉的开发方法,减少服务器访问(通常在汽车行业,UI 和系统混乱是单独的硬件,其中系统部分具有 RT 操作系统)。
由于唯一的客户端是内置浏览器,因此上述缺点(如 JS 可用性、服务器端日志记录、安全性)不再重要。
评论
2. 使用 SPA,我们不需要使用额外的查询来下载页面。
我仍然需要学习很多东西,但自从我开始学习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、Amazon。他们不玩,他们有最伟大的工程师研究这一切。因此,如果您没有看到优势,您最初可以信任它们,并希望在未来发现它们。
但重要的是使用良好的 SPA 设计模式。您可以使用像 AngularJS 这样的框架。不要尝试在不使用良好的设计模式的情况下实现 SPA,因为您最终可能会遇到混乱。
评论
SPA的一个主要缺点 - SEO。直到最近,Google 和 Bing 才开始通过在抓取过程中执行 JavaScript 来索引基于 Ajax 的页面,并且在许多情况下,页面的索引仍然不正确。
在开发 SPA 时,您将被迫处理 SEO 问题,可能是通过对所有网站进行后期渲染并创建静态 html 快照供爬虫使用。这将需要对适当的基础设施进行扎实的投资。
更新 19.06.16:
自从不久前写了这个答案以来,我在单页应用程序(即 AngularJS 1.x)方面获得了更多的经验 - 所以我有更多的信息可以分享。
在我看来,SPA 应用程序的主要缺点是 SEO,使它们仅限于“仪表板”应用程序。此外,与经典解决方案相比,缓存将面临更困难的时期。例如,在 ASP.NET 缓存非常容易 - 只需打开 OutputCaching 就可以了:整个 HTML 页面将根据 URL(或任何其他参数)进行缓存。但是,在 SPA 中,您需要自己处理缓存(通过使用一些解决方案,如二级缓存、模板缓存等)。
评论
我想证明 SPA 最适合数据驱动应用程序。当然,gmail 是关于数据的,因此是 SPA 的良好候选者。
但是,如果您的页面主要用于显示,例如服务条款页面,那么 SPA 就完全矫枉过正了。
我认为最佳点是拥有一个混合了 SPA 和静态/MVC 样式页面的网站,具体取决于特定页面。
例如,在我正在构建的一个站点上,用户登陆到一个标准的 MVC 索引页。但是,当他们转到实际应用程序时,它会调用 SPA。这样做的另一个优点是 SPA 的加载时间不在主页上,而是在应用程序页面上。主页上的加载时间可能会分散初次访问网站的用户的注意力。
这个场景有点像使用 Flash。经过几年的经验,由于负载系数的原因,仅 Flash 站点的数量下降到接近于零。但作为页面组件,它仍在使用中。
评论
在未首先定义如何解决服务器端的安全性和 API 稳定性问题之前,尽量不要考虑使用 SPA。然后,您将看到使用 SPA 的一些真正优势。具体来说,如果您使用实现 OAUTH 2.0 以确保安全性的 RESTful 服务器,您将实现两个基本的关注点分离,从而降低开发和维护成本。
- 这会将会话(及其安全性)移动到 SPA 上,并减轻服务器的所有开销。
- 您的 API 变得既稳定又易于扩展。
较早暗示,但未明确说明;如果您的目标是部署 Android 和 Apple 应用程序,那么编写一个由本机调用包装的 JavaScript SPA 以在浏览器(Android 或 Apple)中托管屏幕,则无需同时维护 Apple 代码库和 Android 代码库。
我知道这是一个较老的问题,但我想补充单页应用程序的另一个缺点:
如果构建以 Data 语言(如 XML 或 JSON)而不是格式语言(如 HTML)返回结果的 API,则可以实现更大的应用程序互操作性,例如,在企业对企业 (B2B) 应用程序中。这种互操作性有很大的好处,但确实允许人们编写软件来“挖掘”(或窃取)您的数据。这种特殊的缺点对于所有使用数据语言的 API 都是通用的,而对于一般的 SPA 来说却不是(事实上,要求服务器提供预渲染 HTML 的 SPA 可以避免这种情况,但代价是模型/视图分离不佳)。这种缺点所暴露的这种风险可以通过各种方式来缓解,例如请求限制和连接阻塞等。
评论
在我的开发中,我发现使用 SPA 有两个明显的优势。这并不是说在传统的 Web 应用程序中无法实现以下目标,只是我看到了增量的好处,而不会引入额外的缺点。
由于呈现新内容,因此服务器请求较少的可能性并不总是,甚至永远不会是 http 服务器对新 html 页面的请求。但我说潜力是因为新内容很容易需要 Ajax 调用来提取数据,但该数据可能比本身更轻,加上标记,从而提供了净收益。
维护“状态”的能力。简单来说,在进入应用程序时设置一个变量,它将在整个用户体验中可供其他组件使用,而无需传递它或将其设置为本地存储模式。然而,智能地管理这种能力是保持顶级范围整洁的关键。
除了需要 JS(这对 Web 应用程序来说并不是一件疯狂的事情)之外,在我看来,其他值得注意的缺点要么不是特定于 SPA,要么可以通过良好的习惯和开发模式来缓解。
我是一个实用主义者,所以我会尝试从成本和收益的角度来看待这个问题。
请注意,对于我给出的任何缺点,我承认它们是可以解决的。这就是为什么我不把任何事情看作是非黑即白的,而是成本和收益。
优势
- 更轻松的状态跟踪 - 无需使用 cookie、表单提交、本地存储、会话存储等来记住 2 个页面加载之间的状态。
- 每个页面上的样板内容(页眉、页脚、徽标、版权横幅等)在每个典型的浏览器会话中仅加载一次。
- 切换“页面”时没有开销延迟。
弊
- 性能监控 - 双手束缚:我见过的大多数浏览器级性能监控解决方案只关注页面加载时间,例如第一个字节的时间、构建 DOM 的时间、HTML 的网络往返、onload 事件等。不会测量通过 AJAX 更新页面后加载。有一些解决方案可以让你检测代码以记录显式度量值,例如在单击链接时,启动计时器,然后在呈现 AJAX 结果后结束计时器,并发送该反馈。例如,New Relic 支持此功能。通过使用 SPA,您只将自己绑定到一些可能的工具上。
- 安全/渗透测试 - 双手捆绑:当您的整个页面由 SPA 框架动态构建时,自动安全扫描可能难以发现链接。这个问题可能有解决方案,但同样,你限制了自己。
- 捆绑:当您在初始页面加载时下载整个网站所需的所有代码时,很容易陷入这种情况,这对于低带宽连接来说可能表现得很糟糕。您可以捆绑 JavaScript 和 CSS 文件以尝试加载更自然的块,但现在您需要维护该映射并注意通过未实现的依赖项拉入的意外文件(恰好发生在我身上)。同样,可以解决,但要付出代价。
- 大爆炸重构:如果你想做一个重大的架构改变,比如说,从一个框架切换到另一个框架,以尽量减少风险,最好进行增量改变。也就是说,开始使用新的,在某种基础上进行迁移,例如每页、每个功能等,然后删除旧的。使用传统的多页应用程序,你可以将一个页面从 Angular 切换到 React,然后在下一个冲刺中切换另一个页面。有了SPA,要么全有,要么全无。如果要更改,则必须一次性更改整个应用程序。
- 导航的复杂性:工具的存在是为了帮助维护 SPA 中的导航上下文,如 history.js、Angular 2,其中大多数依赖于 URL 框架 (#) 或较新的历史 API。如果每个页面都是一个单独的页面,则不需要任何页面。
- 弄清楚代码的复杂性:我们自然而然地将网站视为页面。多页应用通常按页面对代码进行分区,这有助于提高可维护性。
再一次,我认识到这些问题中的每一个都是可以解决的,但要付出一些代价。 但是,在某种程度上,你把所有的时间都花在了解决你本来可以避免的问题上。这又回到了好处以及它们对你有多重要。
评论
上一个:是否可以在上传前检查图像的尺寸?
下一个:jqGrid 客户端搜索
评论