webpack 官网 (opens new window)
技能树
Webpack 知识图谱-博客 (opens new window)

webpack 是用来搭建前端工程的 它运行在 node 环境中,它所做的事情,简单来说,就是打包

具体来说,就是以某个模块作为入口,根据入口分析出所有模块的依赖关系,然后对各种模块进行合并、压缩,形成最终的打包结果

在 webpack 的世界中,一切皆是模块

# 配置

  • mode (opens new window) 模式

  • entry 和 context (opens new window) 入口和上下文

  • output (opens new window) 输出

    • publicPath (opens new window) 在使用 file-loader 或 url-loader 时,模块中的路径来自于某个 loader 或 plugin,当产生路径时,loader 或 plugin 只有相对于 dist 目录的路径,并不知道该路径将在哪个资源中使用,从而无法确定最终正确的路径
    output: {
      // 该配置会为index.html中引入的<script> <link>等标签中的资源路径添加前缀
      publicPath: "/";
    }
    
    1
    2
    3
    4
  • loader (opens new window)
    loader 用于对模块的源代码进行转换。
    loader 可以使你在 import 或"加载"模块时预处理文件。

    webapck 的本质是一个模块打包工具, 所以 webpack 默认只能处理 JS 文件,不能处理其他文件, 因为其他文件中没有模块的概念, 但是在企业开发中我们除了需要对 JS 进行打包以外, 还有可能需要对图片/CSS 等进行打包, 所以为了能够让 webpack 能够对其它的文件类型进行打包, 在打包之前就必须将其它类型文件转换为 webpack 能够识别处理的模块, 注意:loader 都是用 NodeJS 编写的

  • plugin (opens new window) 插件
    插件(plugin)是 webpack 的支柱功能。用于扩展 webpack 的功能。当然 loader 也是变相的扩展了 webpack ,但是它只专注于转化文件这一个领域。
    而 plugin 的功能更加的丰富,而不仅局限于资源的加载。一个插件就是一个类,可以在打包过程中的特定阶段执行。
    从作用角度简单来讲:loader 帮助我们加载文件资源,而 plugins 则是 loader 的延伸,并不限制于加载文件资源。丰富了 loader 的功能。

  • devtool (opens new window) 源码视图

  • resolve (opens new window) 解析相关的配置

    • alias (opens new window) 路径别名
    • extensions (opens new window) 缺省的文件和后缀名
    • modules (opens new window) webpack 解析模块时应该搜索的目录
         resolve: {
             // 创建 import 或 require 的路径别名
             alias: {
                 "@": path.resolve(__dirname, 'src'),
                 "_": __dirname
             },
             // 使的我们在引入资源时可省略后缀,按此配置顺序查找
             extensions: ['.js', '.json', '.wasm'],  // 默认值
             // webpack 解析模块时应该搜索的目录
             modules: ['node_modules'],  // 默认值
         },
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

# 编译过程

webpack 的作用是将源代码编译(构建、打包)成最终代码

整个过程大致分为三个步骤

  1. 初始化
  2. 编译
  3. 输出

# 初始化

此阶段,webpack 会将CLI 参数配置文件默认配置进行融合,形成一个最终的配置对象。

对配置的处理过程是依托一个第三方库yargs完成的

此阶段相对比较简单,主要是为接下来的编译阶段做必要的准备

目前,可以简单的理解为,初始化阶段主要用于产生一个最终的配置

# 编译

  1. 创建 chunk

chunk 是 webpack 在内部构建过程中的一个概念,译为,它表示通过某个入口找到的所有依赖的统称。

根据入口模块(默认为./src/index.js)创建一个 chunk

每个 chunk 都有至少两个属性:

  • name:默认为 main
  • id:唯一编号,开发环境和 name 相同,生产环境是一个数字,从 0 开始
  1. 构建所有依赖模块

AST 在线测试工具:https://astexplorer.net/

简图

  1. 产生 chunk assets

在第二步完成后,chunk 中会产生一个模块列表,列表中包含了模块 id模块转换后的代码

接下来,webpack 会根据配置为 chunk 生成一个资源列表,即chunk assets,资源列表可以理解为是生成到最终文件的文件名和文件内容

chunk hash 是根据所有 chunk assets 的内容生成的一个 hash 字符串
hash:一种算法,具体有很多分类,特点是将一个任意长度的字符串转换为一个固定长度的字符串,而且可以保证原始内容不变,产生的 hash 字符串就不变

简图

  1. 合并 chunk assets

将多个 chunk 的 assets 合并到一起,并产生一个总的 hash

# 输出

此步骤非常简单,webpack 将利用 node 中的 fs 模块(文件处理模块),根据编译产生的总的 assets,生成相应的文件。

# 总过程

# 涉及术语

  1. module:模块,分割的代码单元,webpack 中的模块可以是任何内容的文件,不仅限于 JS
  2. chunk:webpack 内部构建模块的块,一个 chunk 中包含多个模块,这些模块是从入口模块通过依赖分析得来的
  3. bundle:chunk 构建好模块后会生成 chunk 的资源清单,清单中的每一项就是一个 bundle,可以认为 bundle 就是最终生成的文件
  4. hash:最终的资源清单所有内容联合生成的 hash 值
  5. chunkhash:chunk 生成的资源清单内容联合生成的 hash 值
  6. chunkname:chunk 的名称,如果没有配置则使用 main
  7. id:通常指 chunk 的唯一编号,如果在开发环境下构建,和 chunkname 相同;如果是生产环境下构建,则使用一个从 0 开始的数字进行编号