为什么网络应用程序要通过网络传输HTML?

8
这个问题涉及到Web应用程序。我在Web应用程序开发方面经验非常少,可能会忽略一些非常明显的点/问题。请指出它们。
据我了解,在大多数Web应用程序中,Web服务器将HTML通过网络发送到客户端(浏览器)。每次进行HTTP请求时都会发生这种情况。我觉得这非常浪费带宽。
1)由于浏览器可以运行JavaScript,为什么我们不只发送一个JavaScript程序,该程序可以生成网页的HTML内容(然后浏览器呈现)。
2)此外,浏览器可能会缓存JavaScript程序,下次服务器只需要发送数据。协议可能涉及浏览器发送其拥有的“程序版本”。
考虑一个相对简单的网站Hacker News [http://news.ycombinator.com]作为例子。让我们将数据(30篇帖子+它们的元数据)与其呈现分开。在假设1)的情况下,服务器可以发送数据(例如JSON)+一个生成HTML的JavaScript程序。这个gist展示了这个想法。这个特定例子的30个帖子的数据以JSON [http://www.json.org/js.html]格式传输。对于这个特定的例子,传输的数据被切成了1/2(数据+JavaScript的大小 / HTML的大小)。此外,如果浏览器能够执行假设2),则每次访问时传输的数据减少到1/4(数据的大小 / HTML的大小)。【注:这种分析没有考虑压缩;gzip、deflate非常成功地减小了HTML的大小。但是,预防胜于治疗,不是吗?】
我至少看到以下优点: * 对于大多数网页,它将减少通过网络传输的数据量。 * 强制Web应用程序将数据与其呈现分开。
缺点可能包括-更复杂的浏览器,运行JavaScript程序以生成HTML所需的时间(这可能会被数据大小的减小所抵消)。
现在我的问题是-为什么不以这种方式开发Web应用程序,或者为什么Web应用程序要通过网络发送HTML?毕竟,Web服务器(发送HTML)根本不关心HTML,那么为什么它首先要生成它,然后再通过网络发送它呢?

2
生成 HTML 的 JS 实际上比 HTML 本身更大,不是吗? - tenor
1
有很多网络应用程序可以这样工作。 - Pointy
2
像GMail这样的应用程序基本上就是按照您所说的那样运作。通常,服务器会发送一个骨架HTML文件,但之后更新是通过客户端代码完成的,该代码解释了更多“纯”数据响应以进行异步HTTP请求。事实上,Stackoverflow本身也做了很多这样的工作。 - Pointy
3
相比之下,像“黑客新闻”这样的应用程序应尽可能在服务器端完成大部分工作,因为它的目标受众(程序员)往往是少数几个知道可以关闭JavaScript并且有时确实会关闭JavaScript、知道可以使用普通的(非智能手机)电话浏览网页并且有时确实会这样做、了解文本模式用户代理如elinks和lynx甚至wget和curl,并且确实会不时使用它们的人群之一。总的来说,程序员们喜欢你的网站是纯HTML的。 - slebetman
1
搜索引擎对“程序结构”也不太满意。我认为REST风格几乎会带来与使用Flash、Java或任何其他“可脚本化”语言相同的问题。因此,如果您没有静态的“h1”,那么您的标题将不容易从Google等搜索引擎中找到。 - BerggreenDK
显示剩余6条评论
8个回答

7

有一些原因,其中一些是历史性的,这并不是一个完整的列表,而只是我的一些经验:

  1. HTML比JS更早,许多脚本和库也比JS更早。
  2. 旧版浏览器(如IE≤6)具有糟糕、不一致的JS引擎,它们的渲染引擎在处理HTML时更加一致。因此,许多库和脚本都是在一致的JS出现之前编写的。
  3. 如果构建不正确,按照您建议的方式编写的应用程序调试起来非常困难(我们公司就有一个这样的应用程序,需要30分钟才能找到实际生成的html代码片段)。
  4. 正确地完成这项工作需要更多的工作量——为什么不使用模板或静态文档或其他更简单的东西呢?
  5. 这并不是真正的问题——HTML可以很好地压缩。
  6. 您建议的做法确实被采用了——它被称为AJAX(好吧,AJAX比这更通用,但你们都知道我想说什么)。
  7. 对于大多数纯文本用户代理(包括大多数搜索引擎使用的代理),它根本无法工作。如果这个页面服务于大部分您的内容,那么让Google易于解析通常是一个好主意。

5
显而易见的原因是,当我们开始发送HTML时,JavaScript并不存在,而HTML是改进纯文本文档发送的一种方式。
我们现在不这样做的原因是:我们避免在不是真正问题的问题上使用复杂的解决方案。
平均互联网连接速度接近每秒下载近1M字节,Web浏览器能够很好地解析并开始呈现HTML,即使它还没有准备好。它们也非常擅长并行下载页面上的资源。如果我们想要节省一些字节,代价是一些计算周期,我们在发送之前对内容进行gzip压缩。问题得到解决。
值得注意的是,在复杂的网页中我们使用AJAX这种技术(以Github的源代码浏览为例),它可以让事情变得更棒!

浏览器可能很高兴,但我不禁感到服务器和连接对这种安排过于满意 :). 在Web应用程序中,大多数瓶颈不是在服务器端吗? - na_ka_na
当然可以,但这与带宽无关。通常,在需要扩展的CPU周期需求增加后,最大的瓶颈就变成了数据库访问。并发性、即时可用的数据和可扩展性是更相关的问题。这就是为什么每天都会有N+1个新的数据库系统出现(CloudDB、Cassandra等等):P - coreyward

2
您建议的基本上就是像ExtJS这样的JavaScript全栈框架所做的事情。 您可以创建丰富的数据密集型应用程序,而无需编写任何HTML - 只需要足够引用必要的.js库的HTML即可。 所需的布局、网格、表单等复杂DOM都由框架创建。

特别是在移动应用程序中,发送一个HTML页面,然后通过网络发送JSON并在客户端渲染变得越来越普遍。 - zmanian

2
你所建议的可以做到,而且已经在做了。请记住,网页过去是静态文档。全面的基于Web的应用程序是一个相对较新的想法。
我还建议,特别是在页面被gzipped发送时,并不一定更高效。

1
简单的答案是HTML更老。为什么很多编译器没有完全实现C99?他们认为1989年已经足够新了。此外,JavaScript对人们的浏览器施加了更多的控制,而他们似乎并不想要这样。条件语句和编码数据构成了安全问题,有些人希望一开始就把这个问题封闭起来。的确,HTML是一种非常低效的标记语言,但与从互联网下载的图像相比,其大小微不足道。那个网站图标占用的数据量与页面本身一样大,而它只有16个像素。

@匿名,你提出了一个非常有价值的观点,尺寸可能微不足道,但是对于网站图标而言,它们不是被缓存了吗?为什么我们不能缓存所有静态数据呢? - na_ka_na
你可以这样做。服务器可以发送一个头部信息告诉客户端缓存网页本身以及任何图片或其他内容。在你点击刷新按钮、清除缓存或退出浏览器之前,服务器完全控制着缓存。 - Anonymous
16*16=256*(32/8)+BMP_HEADER_BYTES = 1KB + 52B。根据Chrome开发者工具,这个页面大约有45KB。但是,400x100像素的图片就是另一回事了。 - Mateen Ulhaq
是的。嗯,Stack Overflow是一个比较大的网站,有很多菜单之类的东西,但是确实,更大的图片才是真正让你感到困扰的。 - Anonymous

1
一个 Web 应用程序的服务器端代码在服务器端执行许多 HTML 模板工作的一个很好的原因是,在许多服务器环境中,将服务器端数据结构(对象图)捆绑起来以便轻松地传递给客户端并不容易。可能会在服务器端数据结构中保存一些真正不应该传递到客户端的信息。因此,为了发送“纯”数据响应,服务器必须在传送 JSON 之前删除敏感数据。这不是无法解决的问题,但我不知道有多少服务器框架可以方便地解决这个问题。
服务器直接、无限制地访问数据库和其他使应用程序工作的一切:用户首选项、历史记录、帐户详细信息、系统设置等等。为了构建一个以客户端为中心的应用程序以进行呈现,意味着要想出方法来保持所有这些信息完整和更新到客户端。对于许多应用程序来说,这可能并不容易。
最后,仅在相对近期才有意义信任浏览器提供足够稳定的平台来构建长时间运行的“应用环境”,作为一个不断更新的网页。通过构建这样的 Web 应用程序,页面有时需要完全重新加载,这样就有许多小的“重新启动”。这是一种廉价而愚蠢的方法,可以控制至少某些类型的内存泄漏。

你提出了很好的观点。您认为“纯数据”服务器+智能客户端实现了更好的关注点分离(业务逻辑数据与呈现),还是整体上更糟,因为现在应用程序的智能被划分了? - na_ka_na
@na_ka_na,我不知道我是否有足够的经验来说这个问题。但我知道的是,大型应用程序往往会积累许多不同的“状态信息维度”,而在“纯数据”类型的应用程序中处理这些信息是一个相当新的挑战,缺乏坚实的普遍接受的框架支持。我认为这是一个有趣的想法,希望看到更多关于这方面的工作。 - Pointy

0

大多数使用大量Javascript的网站实现都不会在DOM完全加载之前开始执行;然后当页面包装器下载完成时,您将获得每个带有“加载屏幕”的页面,但没有任何内容。

此外,请记住并非所有用户都启用了Javascript,并且并非所有浏览器都支持高级Javascript(考虑移动设备)。


0
如果我想让我的应用程序在没有Javascript的情况下工作,我会在响应中发送HTML。我会使用服务器端语言编写HTML渲染代码(大多数情况下不是Javascript),这样可以用于两个目的:提供整个HTML页面和响应XHR时提供HTML片段。
如果Javascript代码仅限于报告UI事件并将innerHTML替换为服务器生成的代码之类的事情,我就不必在不同的语言/框架之间复制任何应用程序逻辑。这种重复问题是服务器端Javascript引起人们兴奋的原因之一。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接