今天浅整理一下webpack的打包过程
一、初始化过程
1、读参:从配置文件和Shell语句读取与合并参数,得出webpack的配置参数
- 配置文件默认下为
webpack.config.js
(可以通过命令的形式指定配置文件) - webpack将各个配置项拷贝到options对象中,然后加载用户配置的**
plugins
**
var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js');
module.exports = {
// 入口文件,是模块构建的起点
entry: './path/to/my/entry/file.js',
// 文件路径指向(可加快打包过程)。
resolve: {
alias: {
'react': pathToReact
}
},
// 生成文件,是模块构建的终点,包括输出文件与输出路径。
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].js'
},
// 这里配置了处理各模块的 loader
module: {
loaders: [
{
test: /.js$/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
],
noParse: [pathToReact]
},
// webpack 各插件对象,在 webpack 的事件流中执行对应的方法。
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
二、编译构建过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iJMuYVDx-1661479557701)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/54f3adf173c9423aa5e3f74d6bb22647~tplv-k3u1fbpfcp-watermark.image?)]
2、创建Compiler
对象: 启动webpack
,创建Compiler
对象(通过上述参数初始化)
Compiler
对象是一个单局全例,负责把控整个webpack
打包的构建流程,负责文件监听和启动编译- 每次热更新和重新构建,
compiler
都会重新生成一个新的compilation
对象,负责此次更新的构建过程 compilation
对象是每一次构建的上下文对象,它包含了当次构建所需要的所有信息
调用Compiler
的run
来真正启动webpack
编译构建流程
3、从入口文件(entry)开始解析
- entry可以有三种不同形式:
string
|object
|array
,分别对应: 一对一(一个入口一个打包文件),多对一(多个入口,一个打包文件),多对多(多个入口,多个打包文件)
4、make编译模块:
- 一个新的 Compilation 创建完毕主开始编译 完毕主开始编译this.hooks.make.callAsync
5、build module模块:
-
对不同文件类型的依赖模块文件使用对应的**
Loader
**进行编译,最终转为Javascript
文件(编译) -
loader的执行顺序是从右向左执行的
module.exports = { //... module: { rules: [ { test: /.(le|c)ss$/, use: ['style-loader', 'css-loader', 'less-loader'], exclude: /node_modules/, }, ], }, }; // 这样的话就是先处理less-loader,再css-loader,再style-loader
-
常见loader:
-
file-loader
: 可以解析项目中URL的引入,将文件拷贝到相应的路径,并修改打包后文件的引入路径,让其指向正确的文件 -
tslint-loader
:通过 TSLint 检查 TypeScript 代码 -
ts-loader
:将 TypeScript 转换成 JavaScript -
eslint-loader
:通过 ESLint 检查 JavaScript 代码 -
style-loader
:动态创建style
标签,将 CSS 代码插入到head
中 -
css-loader
:负责处理@import
、url
等语句。例如import css from
‘file.css’、
url(image.png)` -
less-loader
:将.less
文件内容转换成 CSS -
sass-loader
:将.sass
文件内容转换成 CSS
-
-
在用loader对一个模块转换后,使用acorn解析转换后的内容,输出对应的抽象语法树(AST),从配置的入口模块开始,分析其AST,当遇到
require
等导入其它模块语句时,便将其加入到依赖的模块列表,同时对新找出的依赖模块递归分析,最终搞清所有模块的依赖关系
三、输出流程
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk(配置在entry的模块,或者是动态引入的模块),再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
四、上述过程简而言之
-
初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
-
开始编译: 根据我们的webpack配置注册好对应的插件调用 compile.run 进入编译阶段,在编译的第一阶段是 compilation,他会注册好不同类型的module对应的 factory
-
编译模块: 进入 make 阶段,会从 entry 开始进行两步操作:
- 第一步是调用 loaders 对模块的原始代码进行编译,转换成标准的JS代码,
- 第二步是调用 acorn 对JS代码进行语法分析,然后收集其中的依赖关系。每个模块都会记录自己的依赖关系,从而形成一颗关系树。
-
输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表
-
输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。