# HTTP 资源优化

开篇中提到涉及网络层的有:

  • DNS 解析
  • TCP 连接
  • HTTP 请求/响应

对于 DNS 解析和 TCP 连接两个步骤,前端可以做的努力相对有限,下面直接从 HTTP 开始:

HTTP 优化有两个大的方向: 1、减少请求次数和 2、减少单次请求所花费的时间

# 1、减少请求次数

# 1.1 资源合并

# 雪碧图

雪碧图是将多个小图标合并在一张图中,从而减少图片资源请求数量的一种优化方案。

# 1.2 图片 Base64

Base64 是一种用于传输 8Bit 字节码的编码方式,通过对图片进行 Base64 编码,我们可以直接将编码结果写入 HTML 或者写入 CSS,从而减少 HTTP 请求的次数。

# 1.3 按需加载

引用 webpack 对按需加载的解释 (opens new window)

按需加载或者懒加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。

总结一下常见的按需加载场景有如下几种:

  • 框架中的懒加载
    • vue 的异步组件
    • vue 路由懒加载
    • react 中的 import()React.lazy、基于路由的代码分割等
  • webpack 的按需加载
  • 图片懒加载

详情请看专题:按需加载

# 2、减少单次请求所花费的时间

# 2.1 压缩代码:

Tree-Shaking,uglifyjs-webpack-plugin/terser-webpack-plugin 压缩,Gzip 压缩,

# Tree-Shaking

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup。

新的 webpack 4 正式版本,扩展了这个检测能力,通过 package.json 的 "sideEffects" 属性作为标记,向 compiler 提供提示,表明项目中的哪些文件是 "pure(纯的 ES2015 模块)",由此可以安全地删除文件中未使用的部分。

webpack 打包过程中,对 ES2015 模块代码能够进行 tree-shaking,减少无用代码缩小项目体积大小,起到优化项目的作用。
专题:tree-shaking

# uglifyjs-webpack-plugin/terser-webpack-plugin

uglifyjs-webpack-plugin 使用 uglify-js 来压缩 JavaScript.

http://lisperator.net/uglifyjs/

UglifyJS 是用 JavaScript 编写的 JavaScript 压缩器。 它还包含一些可以利用 JavaScript 代码做一些自动化工作的工具:

  • parser:代码解析器,从 JavaScript 代码生成抽象语法树(AST)的解析器。
  • code generator:代码生成器,从 AST 输出 JavaScript 代码的代码生成器,也提供了获取source map的选项。
  • compressor (optimizer):代码压缩工具(优化工具),它使用transformer API将 AST 优化为更小的 AST。
  • mangler:混淆器,将局部变量的名称(通常地)简化为单个字母。
  • scope analyzer:作用域解析,通过变量在何处被引用或定义等信息来增强 AST 的工具。
  • tree walker:一个简单的 API,允许您在 AST 中的每个节点上执行操作.
  • tree transformer:另一个用于转换树的 API。

webpack 在 v4.26.0 将默认的压缩插件从 uglifyjs-webpack-plugin 改成 teaser-webpack-plugin
https://github.com/webpack/webpack/releases?after=v4.26.1 (opens new window) 原因是:uglifyjs-webpack-plugin 使用的 uglify-es 已经不再被维护而且 uglify-js 不支持 ES6+,取而代之的是一个名为 terser 的分支。terser 分支大部分地保持了 uglify-esuglify-js@3 的 API 和 CLI 的兼容性。所以 webpack 官方放弃了使用 uglifyjs-webpack-plugin,建议使用 terser-webpack-plugin
https://github.com/terser-js/terser (opens new window)

# 2.2 抽离公共代码:CommonsChunkPlugin/SplitChunksPlugin

webpack 的 CommonsChunkPlugin 插件:通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,以便存到缓存中供后续使用。这样后续新加载的页面也使用到公共模块时可以直接从缓存中读取,反之,新的文件本身也要包含所需要的公共模块的代码,体积变大。因此使用 CommonsChunkPlugin,对于新页面来说可以减小体积,请求时也就减少请求的时间了。

最初,chunks(及其内部导入的模块)是通过内部的 Webpack 依赖图中的父子关系连接的。 CommonsChunkPlugin用于避免重复的依赖关系,但是无法进行进一步的优化。
webpack v4 开始,CommonsChunkPlugin 被删除,转而使用了 optimization.splitChunks

optimization.splitChunks 默认配置
开箱即用的 SplitChunksPlugin 应该适合大多数用户。
默认情况下,它仅影响按需加载的 chunks,因为更改初始 chunks 会影响运行项目的 HTML 文件应包含的 script。
webpack 将根据以下条件自动分割 chunks:

  • 可以共享新的 chunks,或者来自 node_modules 文件夹的模块
  • 新的 chunks 将大于 30kb(在 min+gz 之前)
  • 按需加载 chunks 时的并行请求的最大数量将小于或等于 5
  • 初始页面加载时并行请求的最大数量将小于或等于 3

当试图满足最后两个条件时,最好使用较大的 chunks。