核心概念
本质上,webpack 是一个 JavaScipt 应用程序的静态模块打包器,它递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将所有这些模块根据配置打包成一个或多个包(bundle).
模块(modules)
在模块化编程中,将程序分解成离散功能的块,称之为模块.每个模块比完整程序更小的接触面,使得校验,调测,测试更容易.在 webpack 中,模块可是是 js 文件,npm 包,图片,css/sass/less 文件.以如下方式方式表达它们的依赖关系:- ES2015 import 语句
- CommonJS require() 语句
- AMD define 和 require 语句
- css/sass/less 文件中的 @import 语句
- css 样式中
url()
或 HTML 中<img src="">
中的图片链接
包(bundle):包由许多不同的模块生成,是已经加载和编译过的源文件的最终版本,用于代码合并和分隔。
依赖关系图(dependency graph)
当一个文件依赖另一个文件时,webpack 就认为该文件之间有依赖关系.这使得 webpack 可以接收非代码资源(如图像或自定义字体),并把它们当作依赖提供给应用程序.
webpack 从入口起点开始,递归的构建一个依赖图,其包含着所需的每个模块,然后将这些模块打包为 bundle,可由浏览器加载.配置(configuration)
webpack 配置文件,是导出一个对象的 JavaScript 文件。由 webpack 根据该对象定义的属性进行解析。
因为 webpack 配置是标准的 Node.js CommonJS 模块,所以:- 通过 require() 导入其他文件
- 通过 require() 使用 npm 的工具函数
- 使用 JavaScript 控制流表达式
- 对常用值使用常量或变量
- 编写并执行函数来生成部分配置
块 (chunk):是 webpack 中特定术语,在内部用于管理打包过程。包由块组成,块有几种类型(如 entry 和 child),通常块直接输出对应的包,但是有些配置不会产生一对一的关系。
入口起点(entry points)
在 wepack 配置中定义的 entry 属性。- 简单语法
entry: string|Array<string>
- 对象语法
entry:{[entryChunkNume:string]: string|Array<string>}
- 简单语法
输出(output)
在配置中定义的 output 属性,它控制 webpack 像硬盘写入编译文件。多个入口起点,可以只指定一个输出配置。
output 属性的最低要求,将它设置为一个对象,包含filename,输出文件名
和path,输出目录,绝对路径
。
如果配置了多个入口起点,创建了多个单独的“chunk”,则应该使用占位符来确保每个文件具有唯一的名称.1
2
3
4
5
6
7
8
9
10
11{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: _dirname + '/dist'
}
}
// 输入: ./dist/app.js ./dist/search.js模块转换器(loader)
loader 可以将所有类型的文件转化为 webpack 能够处理的有效模块(JavaScript),然后打包处理。本质上,就是将所有类型的文件,转化为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
配置中 loader 有两个目标:- test 属性,标识出某个或某些文件要被 loader 进行转换
- use 属性,进行转换时,应该使用哪个 loader
loader 要定义在module.rules
中,而不是rules
中。1
2
3
4
5
6
7
8
9{
entry:{},
output:{},
module: {
rules: [
{test:/\.txt$/, use:'raw-loader'}
]
}
}
webpack 编译器,当碰到[require(),import 语句中被解析为’.txt’的路径]时,在打包之前,先用
raw-loader
转换。扩展插件(plugin)
webpack 插件是一个具有apply
属性的 JavaScript 对象,apply 属性会被 webpack commpiler 调用,并且 compiler 对象可在整个编译生命周期访问。
在 webpack 运行时的生命周期中会广播许多事件,plugin 可以监听这些事件,并在合适的时机通过 webpack 提供的 API 改变输出结果。模式(mode)
webpack4 默认不需要配置文件,可以通过 mode 选项为 webpack 指定一些默认的配置。mode 分为development
/production
compiler/compilation
- compiler 对象,包含了 webpack 环境所有的配置信息(options,loader,plugins),这个对象在 webpack 启动时被实例化,且是全局唯一的,可简单立理解为 webpack 实例。代表整个 webpack 从启动到关闭的生命周期
- compliation 对象包含了当前的模块资源、编译生成资源、变化的文件等,当 webpack 以开发模式运行时,每当检测到一个文件变化,就有一次新的 compilation 被创建。compilation 对象也提供了许多事件回调供插件做扩展,通过 compilation 也能读取到 compiler 对象。只代表一次新的编译
webpack 构建流程
webpack 的构建流程可分三大阶段:
- 初始化: 启动构建,读取于合并配置参数,加载 plugin,实例化 compiler。
- 编译:从 entry 出发,针对每一个 module串行调用对应的 loader 取转换文件,再找到该 module 依赖的 modular,递归地进行编译处理
- 输出:对编译后的 module 组合成 chunk,把 chunk 转换成文件,输出到文件系统
具体流程概况
webpack 的运行流程是一个串行过程
- 初始化参数:从配置文件或者命令行中读取、合并参数,得出最终配置的参数。
- 开始编译:用最终的配置参数初始化 compiler 对象,加载所有配置的插件,执行对象的
run
方法开始编译。 - 确定入口:根据配置中的 entry 找出所有的入口文件。
- 模块编译:从入口文件出发,调用所有配置的 loader 模块进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过处理。
- 完成模块编译:在经过第四步使用 loader 转换完成所有模块后,得到每个模块转换后的最终内容和它们之间的依赖关系。
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 chunk,再把每个 chunk 转换成一个单独的文件加入到输出列表。
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
在以上过程中,webpack 会在特定的事件点广播出特定的事件,plugin 在监听到事件后会执行特定的逻辑,且可以调用 webpack 提供的 api 改变 webpack 运行结果