我读过SPA和它的优点。我发现他们中的大多数都没有说服力。有3个优点引起了我的怀疑。

问:你能作为SPA的倡导者,证明我的前三个陈述是错误的吗?

                              === ADVANTAGES ===

1. SPA非常适合响应性非常强的网站:

服务器端呈现很难为所有的中间体实现 状态——小视图状态不能很好地映射到url。 单页应用程序的特点是它们能够重绘任何部分 的UI,而不需要服务器往返检索HTML。这 是通过将数据与数据的表示分开来实现的 拥有处理数据的模型层和读取数据的视图层 从模型中。

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

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

哈,用户在访问你的网站时可以下载多少页面?2、3 ?相反,出现了另一个安全问题,你需要把你的登录页面,管理页面等分开到单独的页面。反过来,它又与SPA体系结构冲突。

3.还有其他的优势吗?别再听别人说了。

                            === DISADVANTAGES ===

客户端必须启用javascript。 只有一个入口。 安全。

附注:我做过SPA项目和非SPA项目。我问这些问题是因为我需要加深我的理解。没有伤害七党联盟支持者的意思。不要让我读更多关于SPA的东西。我只是想听听你对此的看法。


当前回答

我知道这是一个老问题,但我想补充单页应用程序的另一个缺点:

If you build an API that returns results in a data language (such as XML or JSON) rather than a formatting language (like HTML), you are enabling greater application interoperability, for example, in business-to-business (B2B) applications. Such interoperability has great benefits but does allow people to write software to "mine" (or steal) your data. This particular disadvantage is common to all APIs that use a data language, and not to SPAs in general (indeed, an SPA that asks the server for pre-rendered HTML avoids this, but at the expense of poor model/view separation). This risk exposed by this disadvantage can be mitigated by various means, such as request limiting and connection blocking, etc.

其他回答

缺点

1. 客户端必须启用javascript。是的,这是SPA的一个明显的缺点。在我的例子中,我知道我可以期望我的用户启用JavaScript。如果你不能,那么你就不能做SPA,就这样。这就像试图将。net应用程序部署到一台没有安装。net框架的机器上。

2. 只有一个入口。我用SammyJS解决了这个问题。2-3天的工作,让你的路由正确设置,人们将能够创建深度链接书签到你的应用程序,并正常工作。你的服务器只需要公开一个端点——“给我这个应用程序的HTML + CSS + JS”端点(把它想象成预编译应用程序的下载/更新位置)——而你编写的客户端JavaScript将处理进入应用程序的实际入口。

3. Security. This issue is not unique to SPAs, you have to deal with security in exactly the same way when you have an "old-school" client-server app (the HATEOAS model of using Hypertext to link between pages). It's just that the user is making the requests rather than your JavaScript, and that the results are in HTML rather than JSON or some data format. In a non-SPA app you have to secure the individual pages on the server, whereas in a SPA app you have to secure the data endpoints. (And, if you don't want your client to have access to all the code, then you have to split apart the downloadable JavaScript into separate areas as well. I simply tie that into my SammyJS-based routing system so the browser only requests things that the client knows it should have access to, based on an initial load of the user's roles, and then that becomes a non-issue.)

优势

A major architectural advantage of a SPA (that rarely gets mentioned) in many cases is the huge reduction in the "chattiness" of your app. If you design it properly to handle most processing on the client (the whole point, after all), then the number of requests to the server (read "possibilities for 503 errors that wreck your user experience") is dramatically reduced. In fact, a SPA makes it possible to do entirely offline processing, which is huge in some situations. Performance is certainly better with client-side rendering if you do it right, but this is not the most compelling reason to build a SPA. (Network speeds are improving, after all.) Don't make the case for SPA on this basis alone. Flexibility in your UI design is perhaps the other major advantage that I have found. Once I defined my API (with an SDK in JavaScript), I was able to completely rewrite my front-end with zero impact on the server aside from some static resource files. Try doing that with a traditional MVC app! :) (This becomes valuable when you have live deployments and version consistency of your API to worry about.)

因此,底线是:如果您需要脱机处理(或者至少希望您的客户端能够在偶尔的服务器中断中存活)—极大地降低您自己的硬件成本—并且您可以假设JavaScript和现代浏览器,那么您需要一个SPA。在其他情况下,这更像是一种权衡。

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

我仍然需要学习很多,但自从我开始学习SPA,我喜欢他们。

这一点可能会带来巨大的不同。

在许多不是SPA的web应用程序中,您将看到它们仍然会检索并向发出ajax请求的页面添加内容。因此,我认为SPA超越了考虑:如果要使用ajax检索和显示的内容是整个页面,该怎么办?而不仅仅是页面的一小部分?

让我来展示一个场景。假设你有两页纸:

带有产品列表的页面 查看特定产品详细信息的页面

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

获取带有产品详细信息的json对象的请求 获取一个HTML模板的请求,其中将插入产品详细信息

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

然后返回到列表(没有为此做任何请求!)并打开另一个产品。这一次,将只有一个ajax请求来获取产品的详细信息。html模板将是相同的,所以你不需要再次下载。

You may say that in a non SPA, when you open the product details, you make only 1 request and in this scenario we did 2. Yes. But you get the gain from an overall perspective, when you navigate across of many pages, the number of requests is going to be lower. And the data that is transferred between the client side and the server is going to be lower too because the html templates are going to be reused. Also, you don't need to download in every requests all those css, images, javascript files that are present in all the pages.

另外,让我们假设您的服务器端语言是Java。如果你分析我提到的两个请求,一个下载数据(你不需要加载任何视图文件和调用视图渲染引擎),另一个下载和静态html模板,这样你就可以有一个HTTP web服务器,可以直接检索它,而不需要调用Java应用服务器,没有计算!

最后,大公司也在使用SPA: Facebook, GMail,亚马逊。他们不玩,他们有最伟大的工程师研究这些。因此,如果你没有看到它们的优势,你可以一开始就相信它们,并希望在未来的道路上发现它们。

但是使用好的SPA设计模式是很重要的。你可以使用AngularJS这样的框架。不要试图在没有使用好的设计模式的情况下实现SPA,因为您可能会弄得一团糟。

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

这将把会话(以及它的安全性)转移到SPA上,从而减轻服务器的所有开销。 您的API变得既稳定又易于扩展。

前面曾暗示过,但未明确;如果您的目标是部署Android和Apple应用程序,那么编写一个JavaScript SPA,它由本地调用包装,以在浏览器(Android或Apple)中托管屏幕,从而消除了同时维护Apple代码库和Android代码库的需要。

SPA - SEO的一个主要缺点。直到最近谷歌和Bing才开始通过在爬行过程中执行JavaScript来索引基于ajax的页面,但在许多情况下,页面仍然被错误地索引。

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

更新19.06.16:

自从前段时间写了这个答案,我在单页应用(即AngularJS 1.x)方面获得了更多的经验——所以我有更多的信息可以分享。

In my opinion, the main disadvantage of SPA applications is SEO, making them limited to kind of "dashboard" apps only. In addition, you are going to have a much harder times with caching, compared to classic solutions. For example, in ASP.NET caching is extreamly easy - just turn on OutputCaching and you are good: the whole HTML page will be cached according to URL (or any other parameters). However, in SPA you will need to handle caching yourself (by using some solutions like second level cache, template caching, etc..).

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

请注意,对于我给出的任何缺点,我都认识到它们是可以解决的。这就是为什么我不把任何事情看得非黑即白,而是成本和收益。

优势

更容易的状态跟踪-不需要使用cookie,表单提交,本地存储,会话存储等来记住2个页面加载之间的状态。 每个页面(页眉、页脚、logo、版权横幅等)上的样板内容在每次典型的浏览器会话中只加载一次。 切换“页面”时没有开销延迟。

缺点

Performance monitoring - hands tied: Most browser-level performance monitoring solutions I have seen focus exclusively on page load time only, like time to first byte, time to build DOM, network round trip for the HTML, onload event, etc. Updating the page post-load via AJAX would not be measured. There are solutions which let you instrument your code to record explicit measures, like when clicking a link, start a timer, then end a timer after rendering the AJAX results, and send that feedback. New Relic, for example, supports this functionality. By using a SPA, you have tied yourself to only a few possible tools. Security / penetration testing - hands tied: Automated security scans can have difficulty discovering links when your entire page is built dynamically by a SPA framework. There are probably solutions to this, but again, you've limited yourself. Bundling: It is easy to get into a situation when you are downloading all of the code needed for the entire web site on the initial page load, which can perform terribly for low-bandwidth connections. You can bundle your JavaScript and CSS files to try to load in more natural chunks as you go, but now you need to maintain that mapping and watch for unintended files to get pulled in via unrealized dependencies (just happened to me). Again, solvable, but with a cost. Big bang refactoring: If you want to make a major architectural change, like say, switch from one framework to another, to minimize risk, it's desirable to make incremental changes. That is, start using the new, migrate on some basis, like per-page, per-feature, etc., then drop the old after. With traditional multi-page app, you could switch one page from Angular to React, then switch another page in the next sprint. With a SPA, it's all or nothing. If you want to change, you have to change the entire application in one go. Complexity of navigation: Tooling exists to help maintain navigational context in SPA's, like history.js, Angular 2, most of which rely on either the URL framework (#) or the newer history API. If every page was a separate page, you don't need any of that. Complexity of figuring out code: We naturally think of web sites as pages. A multi-page app usually partitions code by page, which aids maintainability.

我再次承认,这些问题中的每一个都是可以解决的,只是需要付出一定的代价。 但总有一天,你把所有的时间都花在了解决问题上,而这些问题本来是可以避免的。这又回到了益处以及它们对你的重要性上。