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 的运行结果。