本文讲的是webpack & HTTP/2,
让我们从 HTTP/2 的一个传言开始:
有了 HTTP/2,你就不再需要打包模块了。
HTTP/2 可以多路复用,所有模块都可以并行使用同一个连接,因此多个请求不再需要多余的往返开销。每个模块都可以独立缓存。
很遗憾,现实并不如意。
以前的文章
下面的文章详细解释了相关信息,并且做了一些实验来验证。你可以阅读它们(或者跳过它们,只看总结)。
文章主旨:
- 相比拼接为一个文件,多个文件传输仍然有 协议开销(protocol overhead)。
- 相比多个小文件,单文件方式对压缩更友好。
- 相比处理单个大文件,服务器处理多个小文件较慢。
因此我们需要在两者中间取得一个折中。我们将模块分为 n 个包,n 大于 1,小于模块数。改变其中一个模块使其缓存失效,因为相应的包只是整个应用的一部分,其它的包的缓存仍然有效。
更多的包意味着缓存命中率更高,但不利于压缩。
AggressiveSplittingPlugin
webpack 2 为你提供了这样的工具。webpack 内部大多都是这样,将一组模块组装成块(chunk)输出一个文件。我们还有一个优化阶段可以改变这些块(chunk),只是需要一个插件来做这个优化。
插件 AggressiveSplittingPlugin 将原始的块分的更小。你可以指定你想要的块大小。它提高了缓存,但不利于压缩(对 HTTP/1 来说也影响传输时间)。
为了结合相似的模块,它们在分离之前会按照路径的字母顺序排序。通常在同一目录下的文件往往是相关的,从压缩来看也是一样。通过这种排序,它们也就能分离到相同的块中了。
对于 HTTP/2 我们现在有高效的分块方式了。
修改应用
但这还没结束。当应用更新时我们要尽量复用之前创建的块。因此每次 AggressiveSplittingPlugin 都能够找到一个合适的块大小(在限制内),并将块的模块(modules)和哈希(hash)保存到 records 中。
Records 是 webpack 编译过程中编译状态的概念,可以通过 JSON 文件存取。
当再次调用 AggressiveSplittingPlugin,在尝试分离剩余模块之前,它会先尝试从 records中恢复块。这就确保已缓存的块能够被复用。
启动和服务(Bootstrapping and Server)
使用这项技术的应用不再输出包含在 HTML 文件中的单独文件,相反,它输出多个需要被加载的块(chunk),应用就能使用多个 script 标签(并行)加载每个块。就像这样:
<script src="1ea296932eacbe248905.js"></script>
<script src="0b3a074667143853404c.js"></script>
<script src="0dd8c061aff2a2791815.js"></script>
<script src="191b812fa5f7504151f7.js"></script>
<script src="08702f45497539ef6ea6.js"></script>
<script src="195c9326275620b0e9c2.js"></script>
<script src="19817b3a0378aedb2143.js"></script>
<script src="0e7a65e649387d773247.js"></script>
<script src="13167c9702de79d2f4fd.js"></script>
<script src="1154be40ff0e8dd16e9f.js"></script>
<script src="129ce3c198a25d9ace74.js"></script>
<script src="032d1fc9a213dfaf2c79.js"></script>
<script src="07df084bbafc95c1df47.js"></script>
<script src="15c45a570bb174ae448e.js"></script>
<script src="02099ada43bbf02a9f73.js"></script>
<script src="17bc99aaed6b9a23da78.js"></script>
<script src="02d127598b1c99dcd2d0.js"></script>
webpack按时间先后顺序输出这些块。最旧的文件先执行,最新的在最后。浏览器可以先执行已被缓存的块,同时加载最新的文件 -- 旧文件更可能已经被缓存。
当 HTML 文件被请求时,HTTP/2 服务端推送可以将这些块推送给客户端。也是因为旧文件更可能已经被缓存,最好能先推送最新的文件。如果已经有缓存,客户端可以取消服务端的推送,但这需要一次往返。
webpack 将代码分离用于 按需加载,可以处理并行请求。
结论
webpack 2 为你提供了用于 HTTP/2 的,能改善缓存和传输的工具。不用担心你的技术栈不面向未来了。
注意 AggressiveSplittingPlugin 仍然是实验特性。
我对你的使用体验很感兴趣哦~
原文发布时间为:2017年10月19日
本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。