7

我希望在全球范围的 Web 应用程序方面有更多经验的人能够澄清我的一些问题、假设和可能的误解。

让我们假设一个站点(大量客户端/动态组件)在全球拥有数十万用户,并且从一个位置(比方说中欧)提供资源。

  1. 如果应用程序依赖于流行的 JavaScript 库,最好从 Google CDN 获取它并将其编译成一个缩小的 JS 文件(以及所有特定于应用程序的 JavaScript)还是从 Google CDN 单独加载它?
  2. Assetic VS headjs:加载单个 JS 文件或并行加载所有脚本(按依赖顺序执行)是否更有意义?

我的假设(请纠正我):

将所有特定于应用程序的/本地 JS 代码编译到一个文件中,使用 Google 等流行库的 CDN 等,但通过 headjs 并行加载所有这些似乎是最佳选择,但我不确定。服务器端将第三方 JS 和特定于应用程序的 JS 编译到一个文件中似乎几乎违背了使用 CDN 的目的,因为无论如何该库可能都为用户缓存在某个地方。

除了缓存之外,从 Google 的 CDN 下载第三方库可能比托管应用程序的中央服务器更快。

如果一个流行的 JS 库的新版本发布了,性能有了很大的提升,用应用程序进行测试然后实现:

  • 如果所有的 JS 都被编译成一个文件,那么即使应用程序代码没有改变,每个用户都必须重新下载这个文件。
  • 如果第三方脚本是从 CDN 加载的,那么用户只能从 CDN(或从某处的缓存)下载新版本。

在所描述的情况下,是否有以下任何合理的担忧?

  • 一些用户(或浏览器)一次只能与一个主机名建立一定数量的连接,因此从第三方 CDN 检索一些脚本将导致整体加载时间更快。
  • 一些用户可能在受限环境中使用应用程序,因此应用程序的域可能会被列入白名单,但 CDN 的域不会。(如果这可能是现实问题,是否有可能尝试从 CDN 加载并在出现故障时从中央服务器加载?)
4

3 回答 3

8

将所有应用程序特定/本地 JS 代码编译到一个文件中

由于我们的一些关键目标是减少 HTTP 请求的数量最小化请求开销,因此这是一种非常广泛采用的最佳实践。

我们可能考虑不这样做的主要情况是在缓存频繁失效的可能性很高的情况下,即当我们对代码进行更改时。这里总会有权衡:提供单个文件很可能会增加缓存失效率,而提供许多单独的文件可能会导致缓存为空的用户启动速度变慢。

出于这个原因,偶尔内联特定页面的 JavaScript 并不像某些人所说的那样邪恶。但总的来说,将 JS 连接并压缩到一个文件中是很好的第一步。

使用像谷歌这样的 CDN 用于流行的库等。

如果我们谈论的是我们使用的代码相当不可变的库,即不太可能受到缓存失效的影响,我可能更倾向于通过将 HTTP 请求包装到您的整体本地 JS 文件中来保存它们。对于大量基于例如特定 jQuery 版本的大型代码库来说尤其如此。在这种情况下,更改库版本几乎肯定会涉及到对您的客户端应用程序代码的重大更改,从而抵消了将它们分开的优势。

尽管如此,混合请求域是一个重要的胜利,因为我们不希望受到每个域上限的最大连接数的过度限制。当然,子域也可以为此提供服务,但 Google 的域具有无 cookie 的优势,并且可能已经在客户端的 DNS 缓存中。

但是通过headjs并行加载所有这些似乎是最佳的

虽然新兴的 JavaScript“加载器”宿主有很多优势,但我们应该记住,使用它们确实会对页面启动产生负面影响,因为浏览器需要先获取我们的加载器,然后加载器才能请求我们的其余资源。换句话说,对于缓存为空的用户,在开始任何实际加载之前,需要与服务器进行一次完整的往返。再一次,“编译”步骤可以派上用场 - 请参阅require.js以获得出色的混合实现。

确保脚本不会阻止 UI 绘制的最佳方法仍然是将它们放在 HTML 的末尾。如果您希望将它们放在其他地方,asyncdefer属性现在为您提供了这种灵活性。所有现代浏览器都并行请求资产,因此除非您需要支持特定风格的旧客户端,否则这不应该是主要考虑因素。Browserscope 网络表是这类东西的一个很好的参考。可以预见,IE8 是主要攻击者,在加载脚本之前仍会阻止图像和 iFrame 请求。甚至在3.6版本的Firefox 中,除了 iFrame 之外的所有东西都是完全并行的。

一些用户可能在受限环境中使用应用程序,因此应用程序的域可能会被列入白名单,但 CDN 的域不会。(如果这可能是现实问题,是否有可能尝试从 CDN 加载并在出现故障时从中央服务器加载?)

确定客户端机器是否可以访问远程主机总是会导致严重的性能损失,因为我们必须等待它无法连接才能加载我们的保留副本。我更倾向于在本地托管这些资产。

于 2012-08-01T17:32:09.580 回答
4
  1. 由于许多原因,包括更改/依赖项/要求,许多小型 js 文件比少数大型 js 文件要好。
  2. JavaScript/css/html 和任何其他静态内容由任何当前的 Web 服务器(Apache/IIS 和许多其他服务器)非常有效地处理,大多数情况下,一个 Web 服务器能够服务于每秒 100 和 1000 次请求,并且在任何情况下,此静态内容都可能缓存在客户端和您的服务器之间的某处。
  3. 为您想在生产环境中使用的代码使用任何外部(不受您控制)存储库是不可以的(对我和许多其他人来说),您不希望整个站点突然发生、灾难性和不可恢复的故障JavaScript 功能只是因为有人在某个地方按下了提交而不考虑或检查。
于 2012-08-01T16:56:55.940 回答
1

将所有特定于应用程序的/本地 JS 代码编译到一个文件中,使用 Google 等流行库的 CDN 等,但通过 headjs 并行加载所有这些似乎是最佳选择......

我会说这基本上是对的。不要将多个外部库合并到一个文件中,因为——正如你所知道的——这将否定大多数情况下用户的浏览器已经缓存了(单个)资源。

对于您自己的特定于应用程序的 JS 代码,您可能需要考虑的一个因素是更新频率。例如,如果有一个功能核心不会经常更改,但一些较小的组件可能会定期更改,那么仅将核心编译(我假设您的意思是缩小/压缩)到一个文件中同时继续提供较小的零件零碎。

您的决定还应考虑您的 JS 资产的大小。如果——这不太可能,但有可能——你提供了大量的 JavaScript,将它们全部连接到一个文件中可能会适得其反,因为某些客户端(例如移动设备)对它们将缓存的内容有非常严格的限制。在这种情况下,您最好为少数较小的资产提供服务。

这些只是您要注意的随机花絮。我想说的主要一点是,你的第一直觉(上面引用)可能是正确的方法。

于 2012-08-01T17:09:52.923 回答