为什么会这样?或者我的期望不正确吗?
截图(您可以看到协议是http2):
更新 #1:
- 后端运行在 nginx 1.13 上;
- 我正在使用自定义模块加载器,它通过创建带有
async
属性的脚本标签来一次性加载所有脚本; - 截图显示,对于第8行及其后面的内容,浏览器已经收到了下载资源的请求,但是白色部分表明这些脚本已排队,只有在可用插槽时才会实际开始下载(请看第2、3和4行完成后,第8、7和9行开始加载;同样,第11、12、13行和第5、6、7行也是如此)。
为什么会这样?或者我的期望不正确吗?
截图(您可以看到协议是http2):
更新 #1:
async
属性的脚本标签来一次性加载所有脚本;我认为这是Chrome的一个 bug,或者至少是一种不必要的限制。
这很容易测试。
我创建了一个简单的示例 HTML 文件,它会下载同一个 JavaScript 文件的 25 个副本(通过查询参数使其看起来像是不同的资源):
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Lots of JS files</title>
<meta name="robots" content="noindex">
<body>
</body>
<h1>This is a test for Lots of JS files</h1>
<script src="/assets/js/test.js?v=01"></script>
<script src="/assets/js/test.js?v=02"></script>
<script src="/assets/js/test.js?v=03"></script>
<script src="/assets/js/test.js?v=04"></script>
<script src="/assets/js/test.js?v=05"></script>
<script src="/assets/js/test.js?v=06"></script>
<script src="/assets/js/test.js?v=07"></script>
<script src="/assets/js/test.js?v=08"></script>
<script src="/assets/js/test.js?v=09"></script>
<script src="/assets/js/test.js?v=10"></script>
<script src="/assets/js/test.js?v=11"></script>
<script src="/assets/js/test.js?v=12"></script>
<script src="/assets/js/test.js?v=13"></script>
<script src="/assets/js/test.js?v=14"></script>
<script src="/assets/js/test.js?v=15"></script>
<script src="/assets/js/test.js?v=16"></script>
<script src="/assets/js/test.js?v=17"></script>
<script src="/assets/js/test.js?v=18"></script>
<script src="/assets/js/test.js?v=19"></script>
<script src="/assets/js/test.js?v=20"></script>
<script src="/assets/js/test.js?v=21"></script>
<script src="/assets/js/test.js?v=22"></script>
<script src="/assets/js/test.js?v=23"></script>
<script src="/assets/js/test.js?v=24"></script>
<script src="/assets/js/test.js?v=25"></script>
</html>
我接着做了同样的事情,但加上了async属性,以防万一Chrome在处理Javascript时决定阻止下载:
<script src="/assets/js/test.js?v=01" async=""></script>
<script src="/assets/js/test.js?v=02" async=""></script>
....etc.
再次相同,但使用defer属性:
<script src="/assets/js/test.js?v=01" defer=""></script>
<script src="/assets/js/test.js?v=02" defer=""></script>
....etc.
/assets/js/test.js
文件是空的。因此,除了浏览器添加的依赖项之外,不会有执行延迟或其他依赖项。
我看到了一些有趣的结果!这都是使用Chrome 60.0.3112.78或60.0.3112.101,并且我正在使用Apache,但看到与您在Nginx上看到的相同结果。
使用HTTP/2服务器,我们看到以下结果:
使用普通的script
标签,所有脚本都并行加载(但可能按顺序执行)。不存在HTTP/1.1下的6个连接限制:
使用异步script
标签,脚本以6个为一组并行加载-与您提到的完全相同:
点击它们可以看到它们通过HTTP/2下载。
使用延迟script
标签时,结果与使用异步标签相同-限制同时进行6次下载。
这没有意义- Chrome限制了您的JavaScript下载,但只有在使用异步或延迟模式来提高下载不阻止呈现的情况下才会出现!
正如sbordet所述,在视口中的图像上也没有发生同样的事情-因此Chrome上的多路复用确实有效,但它看起来对于异步或延迟模式下的JavaScript受到无谓的限制。如果您考虑不再在HTTP/2下捆绑脚本,则这是一个真正的限制,许多人建议您不再需要这样做。
Firefox和Edge上不会发生相同的情况。但在Opera(基于Chromium的浏览器)上会发生。
这就是坏消息。好消息是他们“可能”已经解决了这个问题。当我尝试使用Chrome Canary(62.0.3190.0)时,我无法重复此行为。但是,当我在Canary中使用Web Page Test(其在用户代理字符串中提供了62.0.3190.1,因此应该几乎相同),它是可重复的,因此并不确定他们是否真的解决了这个问题...
我已经向Chrome团队报告了这个错误,所以将看看他们会说什么:https://bugs.chromium.org/p/chromium/issues/detail?id=757191
总的来说,HTTP/2在服务器和客户端上似乎还处于一种不稳定状态,因为双方都调整其实现以获取对这个仍然相对较新的协议的最佳使用。尽管如此,这让人惊讶的是见到Chrome遇到这个问题,因为谷歌用他们的SDPY实现(HTTP/2是基于此的)启动了这个功能,所以您会期望他们走在前面而不是落后...
**更新**
Chrome团队回复并确认这是Chrome中当前实现的HTTP/2限制。当同时调用多个资源时,他们发现性能问题,因为HTTP/2允许,因此限制非关键