如何优化服务和加载JavaScript文件?

时间:2012-08-01 16:18:49

标签: javascript networking download cdn assetic

我希望有更多全球规模网络应用程序经验的人可以澄清一些问题,假设和可能存在的误解。

让我们来一个假设的网站(大量的客户端/动态组件),全球有数十万用户,来自一个地方的服务来源(让我们说中欧)

  1. 如果应用程序依赖于流行的JavaScript库,那么从Google CDN中获取它并将其编译成一个简化的JS文件(以及所有特定于应用程序的JavaScript)或者将其与Google CDN分开加载会更好吗?
  2. Assetic VS headjs:加载一个JS文件或并行加载所有脚本(按依赖顺序执行)更有意义吗?
  3. 我的假设(请纠正我):

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

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

    如果发布一个流行的JS库的新版本,性能大幅提升,则使用该应用程序进行测试,然后实施:

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

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

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

3 个答案:

答案 0 :(得分:8)

  

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

由于我们的一些主要目标是reduce the number of HTTP requestsminimize request overhead,因此这是一种广泛采用的最佳做法。

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

出于这个原因,偶尔勾画一下特定于页面的JavaScript并不像有些人说的那么邪恶。一般来说,将JS连接和缩小为一个文件是一个很好的第一步。

  

使用像谷歌这样的CDN用于流行的图书馆等。

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

仍然是mixing request domains is an important win,因为我们不希望被每个域名上限的最大连接过度限制。当然,子域名也可以用于此,但Google的域名具有无cookie的优势,并且可能已经在客户端的DNS缓存中。

  

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

虽然新兴的JavaScript“加载器”主机有优势,但我们应该记住,使用它们确实会对页面启动产生负面影响,因为浏览器需要在加载器请求我们的其余部分之前获取加载器。资产。换句话说,对于具有空缓存的用户,在开始任何实际加载之前需要到服务器的完整往返。同样,“编译”步骤可以拯救 - 请参阅require.js以获得出色的混合实现。

确保脚本不阻止UI绘制的最佳方法仍然是将它们放在HTML的末尾。如果您希望将它们放在其他位置,asyncdefer属性现在可以为您提供灵活性。所有现代浏览器并行请求资产,因此除非您需要支持特定版本的旧客户端,否则这不应该是主要考虑因素。 Browserscope network table是这类事情的绝佳参考。 IE8可以预见为主要攻击者,在加载脚本之前仍会阻止图像和iFrame请求。即使回到3.6,Firefox也完全并行化了除iFrame之外的所有内容。

  

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

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

答案 1 :(得分:4)

  1. 许多小js文件比少数大文件好,原因很多,包括更改/依赖/要求。
  2. JavaScript / css / html和任何其他静态内容由任何当前的Web服务器(Apache / IIS和许多其他服务器)非常有效地处理,大多数情况下,一个Web服务器能够提供100和1000个请求/秒,无论如何,这个静态内容可能会缓存在客户端和服务器之间的某个位置。
  3. 使用任何外部(不受您控制)存储库来获取要在生产环境中使用的代码是NO-NO(对于我和许多其他人),您不希望发生突发性,灾难性和无法恢复的故障。你的整个网站的JavaScript功能只是因为有人在没有思考或检查的情况下按下提交。

答案 2 :(得分:1)

  

使用,将所有特定于应用程序的/本地JS代码编译到一个文件中   像谷歌的流行图书馆等CDN,但加载所有   这些并行的headjs似乎是最佳的......

我说这基本上是正确的。不要将多个外部库合并到一个文件中,因为 - 正如您所知道的那样 - 这将取消用户浏览器已经缓存(个别)资源的大部分情况。

对于您自己的特定于应用程序的JS代码,您可能想要考虑的一个因素是更新它的频率。例如,如果有一个功能核心不经常更改,但一些较小的组件可能会定期更改,那么只有编译(我认为你的意思是缩小/压缩)核心成为一个文件,同时继续为其提供服务可能是有意义的。零碎的小零件。

您的决定还应考虑您的JS资产的规模。如果 - 并且这不太可能,但可能 - 您正在提供非常大量的 JavaScript,将其连接到一个文件可能会适得其反,因为某些客户端(例如移动设备)对其有非常严格的限制他们会缓存什么。在这种情况下,您最好还是提供一些较小的资产。

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