第一章 工程化 - 构建工具 - Webpack - 【 webpack 基本构建流程 】

发布时间 2023-03-28 15:21:42作者: caix-1987

webpack 概述

webpack 是什么
1、webpack 是一个现代 JavaScript 应用程序的静态模块打包器 (module bundle),当 webpack 处理应用程序时,它会递归的构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或者多个的 bundle

2、webpack 是一个打包模块化 JavaScript 的工具,它会从入口模块出发,识别出源码中的模块化导入语句,递归地找出入口文件的所有依赖,将入口和其所有的依赖打包到一个单独的文件中,是工程化、自动化思想在前端开发中的体现

3、webpack 是一个用于现代 JavaScript 应用程序的 静态模块 打包工具

   静态模块:指的是开发阶段,可以被 webpack 直接引用的资源 【 可以直接被获取打包进 bundle.js 的资源 】
webpack 的能力
1、代码编译能力

   提高效率,解决浏览器兼容问题 【 将开发阶段的 ES6+ 语法、TypeScript 脚本编译为 ES5 低版本代码 ... 】

2、模块整合能力

   提高性能,可维护性,解决浏览器频繁请求文件的问题 【 将多个模块文件打包成一个 bundle 】

3、万物皆可模块化

   项目维护性增强,支持不同种类的前端模块类型,统一的模块化方案,所有资源文件的加载都可以通过代码控制 【 .ts、.js、.png、.scss 文件等 】
webpack 配置 核心概念
1、chunk

  指代码块,一个 chunk 可能由多个模块组合而成,也用于代码 合并 与 分割
  
2、bundle

  资源经过 webpack 流程解析编译后最终输出的成果文件
  
3、entry

  1、顾名思义,就是入口起点,用来告诉 webpack 用哪个文件作为构建 依赖图 的起点
  
  2、webpack 会根据 entry 递归的去寻找依赖,每个依赖都将被它处理,最后输出到打包成果中
  
4、output

  output 配置描述了 webpack 打包的输出配置,包含输出文件的命名、位置等信息
  
5、loader

  1、默认情况下,webpack 仅支持 .js .json 文件,通过 loader,可以让它解析其他类型的文件,充当翻译官的角色
  
  2、理论上只要有相对应的 loader,就可以处理任何类型的文件
  
6、plugin 【 插件 】

  loader 主要的职责是让 webpack 认识更多的文件类型,而 plugin 是职责是让其可以控制构建流程,从而执行一些特殊的任务
  
  插件的功能非常强大,可以完成各种各样的任务
  
7、mode 【 模式 】

  1、webpack 4.0 开始,支持 零 配置,旨在为开发人员减少上手难度
  
  2、同时加入 mode 的概念,用于指定打包的目标环境,以便在打包过程中启用 webpack 针对不同环境下内置的优化
  
  3、不同环境下我们需要针对性地对代码进行调整以适配不同环境,mode 可以满足这一需求
  
  4、在webpack里,通过选择 development, production 或 none 之中的一个,来设置mode参数
  
  5、从而可以启用 webpack 内置在相应环境下的优化,其默认值为 production

webpack 基本构建流程

1、webpack 的 运行流程 是一个 串行 的过程,它的工作流程就是将各个插件串联起来

2、在运行过程中会 广播事件,插件只需要监听它所关心的事件,就能加入到这条 webpack 机制中,去改变 webpack 的运作,使得整个系统扩展性良好

3、webpack 从启动到结束会依次执行以下 三 大步骤

  1、初始化流程
  
    从 配置文件 和 Shell 语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数
    
  2、编译构建流程
  
    从 Entry 出发,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module 依赖的 Module,递归地进行编译处理  
    
  3、输出流程
  
    对编译后的 Module 组合成 Chunk,把 Chunk 转换成文件,输出到文件系统  
初始化流程
1、webpack 从配置文件 【 webpack.config.js,或者通过命令的形式指定配置文件 】和 shell 命令 【 或是 scripts 配置的命令 】中读取并合并参数,得到最终参数

2、主要作用是用于激活 webpack 的 加载项 【 loader 】和 插件 【 plugin 】

3、主要涉及 以下 两步 操作

  1、webpack 将 webpack.config.js 中的配置项拷贝到 options 对象中,并加载用户配置的 plugins
  
  2、开始初始化 Compiler 编译对象,该对象掌控着 webpack 生命周期,定义了很多钩子函数,不执行具体的任务,只是进行一些调度工作
编译构建流程
1、根据配置中的 entry 找出所有的入口文件

2、初始化完成后,调用 compiler.watch / compiler.run 来启动编译构建流程,主要流程为

  1、compile 开始编译
  
    主要是构建一个 Compilation 对象,它是编译阶段的主要执行者,主要会依次进行 执行模块创建、依赖收集、分块、打包 等主要任务的对象
  
  2、make 从入口点分析模块及其依赖的模块,创建这些模块对象
  
    得到 Compilation 对象后,就开始从 entry 入口文件开始读取,主要执行 
    addModuleChain,执行 buildModule 进入真正的构建模块 module 内容的过程
  
  3、build-module 构建模块
  
     1、主要调用配置的 loaders,将我们的模块转成标准的 JS模块
     
     2、在用 Loader 对一个模块转换完后,使用 acorn 解析转换后的内容,输出对应的抽象语法树(AST),以方便 Webpack 后面对代码的分析
     
     3、从配置的入口模块开始,分析其 AST,当遇到 require 等导入其它模块语句时,便将其加入到依赖的模块列表,同时对新找出的依赖模块递归分析,最终搞清 所有模块的依赖关系
  
  4、seal 封装构建结果
  
  5、emit 把各个chunk输出到结果文件
输出流程
1、seal 输出资源

  1、这一步主要是要生成 chunks,对 chunks 进行一系列的优化操作,并生成要输出的代码;
  
  2、webpack 会根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表
  
2、emit 输出完成

  1、根据 webpack.config.js output 配置确定输出的路径和文件名
  
  2、在 Compiler 开始生成文件前,钩子 emit 会被执行,这是我们修改最终文件的 最后一个机会
webpack 详细的构建流程
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

1、初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;

2、开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;

3、确定入口:根据配置中的 entry 找出所有的入口文件;

4、编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;

5、完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;

6、输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;

7、输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。