Node js - http2 的捆绑器
Posted
技术标签:
【中文标题】Node js - http2 的捆绑器【英文标题】:Node js - Bundler for http2 【发布时间】:2016-07-02 01:52:29 【问题描述】:我目前正在使用 babel 将 es6 代码转换为 es5 并通过 browserify 将其捆绑以在浏览器中使用。现在我开始使用 http2 服务器(nginx)。
Http2 可以加载多个小文件而不是一个大包时更有效。
如何最好地提供多个 js 文件而不是一个大包?
【问题讨论】:
【参考方案1】:我知道 SystemJS 可以在开发中加载多个文件而无需捆绑,而对于生产,您可以使用 DepCache 来定义您正在导入的模块的依赖树
https://github.com/systemjs/systemjs/blob/master/docs/production-workflows.md
这种方法需要你放弃 browserfy 并改为 systemjs,因为它只使用包。
【讨论】:
感谢您的回答。我会尝试jspm,看看是否合适!【参考方案2】:我看到你直到现在还没有得到你的问题的答案。因此,尽管 HTTP/2 对我来说也是新的(它解释了我的答案的长文本 :-)),但我还是尽力为您提供帮助。
可以在https://blog.cloudflare.com/http-2-for-web-developers/ 页面上找到有关 HTTP/2 的详细信息。我再重复一遍:
停止连接文件 停止内联资产 停止分片域 继续最小化 CSS/javascript 文件 继续从 CDN 加载 通过包含在<head>
中的<link rel='dns-prefetch' href='...' />
继续DNS 预取
...
我想补充两点关于设置HTTP头Cache-Control
和Link
的重要性:
Cache-Control
HTTP 标头(尤其是max-age
、expires
和etag
)。请参阅下面的详细信息。我强烈建议阅读Caching Tutorial。
设置Link
HTTP 标头以使用 HTTP/2 的 SERVER PUSH。
设置 HTTP 头 LINK:
对使用 HTTP/2 的服务器推送功能很重要(参见 here、here)。 RFC2068 的RFC5988 和19.6.1.2 部分描述了已经存在于 HTTP 1.1 中的特性。每个人都知道Content-Type: application/json
,但同样可以设置鲜为人知的Link: <...>; rel=prefetch
,描述为here。例如,可以使用
Link: </app/script.js>; rel=preload; as=script
Link: </fonts/font.woff>; rel=preload; as=font
Link: </app/style.css>; rel=preload; as=style
在 html 页面上设置的此类链接(如 index.html
)将通知 HTTP 服务器将资源与 HTML 页面上的响应一起推送。结果,您节省了不必要的往返和以后的请求(在解析 HTML 文件之后),并且资源将立即显示。您可以考虑在页面中的所有图像上设置 LINK 标题,以提高页面的可见性。请参阅here 附加信息和漂亮的图片,它展示了 HTTP/2 服务器推送的优势。如果您使用 php,那么 the code 可能对您来说很有趣。
大多数网络开发人员会直接或间接地进行一些优化步骤。这些步骤可以在构建过程中完成,也可以通过在 HTTP 响应中设置 HTTP 标头 来完成。一个人必须审查一些流程来关闭某人并包括另一个流程。我试着总结一下我的结果。
你可以考虑使用 webpack 代替 browserify 来排除一些依赖合并。我不知道 browserify 足够好,但我知道 webpack 支持externals
(参见here),它允许从 CDN 加载一些模块。在下一步中,您可以完全删除任何合并,但在所有模块上最小化并设置 cache-control
。
强烈建议从 CDN 加载 CSS/JS/Fonts,这些是您使用的,但不是您自己开发的。 你不应该将这些资源与你的 JavaScript 文件合并(你现在可以用 browserify 做什么)。从您的服务器加载 Bootstrap CSS 不是一个好主意。最好听从here 的建议,使用CDN 代替本地下载所有文件。
如果您检查来自https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js 的响应的HTTP 标头,那么使用CDN 的主要原因很容易理解。你会发现类似cache-control: public, max-age=30672000
和expires:Mon, 06 Mar 2017 21:25:04 GMT
的东西。 Chrome 通常会显示Status Code:200 (from cache)
,您会看到没有流量通过网络。如果您明确地重新加载页面(通过按 F5),那么您将看到一个包含 222 字节和 Status Code:304
的响应。换句话说,文件通常根本不会加载。 jQuery 2.2.1 永远保持不变。下一个版本将有另一个 URL。 HTTPS 的使用确保用户将真正加载 jQuery 2.2.1。如果还不够,可以使用https://www.srihash.org/计算sha384值并使用<link>
或<script>
的扩展形式:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"
integrity="sha384-8C+3bW/ArbXinsJduAjm9O7WNnuOcO+Bok/VScRYikawtvz4ZPrpXtGfKIewM9dK"
crossorigin="anonymous"></script>
如果用户使用链接打开您的页面,则 sha384 哈希将被重新计算和验证(通过 Chrome 和 Firefox)。如果文件还没有在本地缓存中,那么它也会很快被加载。通过从https://code.jquery.com/jquery-2.2.1.min.js 加载相同文件的简短说明,今天使用HTTP 1.1,但从https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js 使用HTTP/2 协议。我建议通过选择 CDN 来测试协议。您可以找到here 现在支持 HTTP/2 的 CDN 列表。与从 https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css 加载 Bootstrap 的方式相同,现在有人会使用 HTTP 1.1,但有人会通过从 https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css 加载相同的数据来使用 HTTP/2。
我花了很多时间来说明 CDN 的最大优势是设置 HTTP 响应的兑现标头和 不可变 URL 的使用。你也可以在你的模块中做同样的事情。
应该考虑缓存从服务器返回的每个内容的时间。您可以使用模块的 URL,其中包含组件的版本号(如/script/mycomponent1.1.12341
),并在每次更改模块时更改版本号的最后一部分。您可以在cache-control
中设置足够长的max-age
值,您的组件将被客户端的Web 浏览器缓存。
最后,我建议您验证是否安装了最新版本的OpenSSL 和最新版本的nginx。我建议您在http://www.webpagetest.org/ 和https://www.ssllabs.com/ssltest/ 中验证您的网站,以确保您不会忘记任何简单的步骤。
【讨论】:
感谢您提供有关 http2 和性能的一些信息。你中间提到了webpack short,它还能单独加载你需要的js文件吗? @blablabla:我认为最好的结果可能是所有 js 文件单独需要,但我建议您进行测试。此外,您应该认为并非所有客户端都已经支持 HTTP/2。我想强调一下,只有在设置好Cache-Control
标头之后,才应该单独加载所有 js。只有当require
几乎每次都从 local Web 浏览器缓存中加载文件而不与服务器进行任何交互时,您的站点才能快速运行。在解决所有问题之前,您应该从 CDN 加载所有外部模块。
@blablabla:我可以想象这样一种场景,即为每个 JS 文件构建完整的依赖关系树并为文件生成 LINK:
HTTP 标头,以便服务器推送具有所有依赖关系的文件。我不能建议这样做的现有解决方案。我只想展示 Web 开发的方向,它现在生成了我们的 HTTP/2。旧工具应更换为新工具。以上是关于Node js - http2 的捆绑器的主要内容,如果未能解决你的问题,请参考以下文章
与 webpack 捆绑时如何使 node.js 在没有 node_modules 的情况下工作?
如何选择 node_modules dist 风格与 webpack 捆绑
如何选择与webpack捆绑的node_modules dist flavor