【webpack系列】1. 从源码角度分析webpack打包产出及核心流程

1,212 阅读3分钟

webpack一直好像是熟悉的陌生人,最近从源码角度通过debug总算是找到了打包的整个线条,揭开了这神秘的面纱。直接按部就班看源码难免会迷糊,带着自己的疑问反查源码就清晰多了。

先从整体纬度出发,这篇文章围绕下面两个问题梳理整体流程:

1. webpack产出的打包文件是什么

首先看第一个问题webpack打包后生成了什么?通过一个最简单的例子进行打包,把代码注释去掉,发现得到一个立即执行函数:

image.png

很多文章都是基于打包后的文件进行分析,我一直好奇这个文件到底如何生成的?虽然大概知道是webpack生成的,但是不知道具体是哪个阶段由谁来生成的。

通过debug源码发现打包产出的非业务逻辑代码原来在MainTemplate.js文件中,总算找到产出文件的影子,小激动了一下,如下图所示:

image.png

可以看出webpack最后打包生成的文件是由runtime运行时(根据资源引入方式不同打包结果也不同)加上业务代码共同组成的。

:对于不同的引入方式,打包内容会不同,如果采用异步引入模块,打包会变成如下内容:

image.png

image.png

结论:webpack打包产出的文件是立即执行函数,这个函数内容会随着模块引入方式而变化,函数是参数是业务代码模块对象(文件路径:文件源码)。

继续看下第二个问题webpack是如何生成打包文件的。

2. webpack是如何生成打包文件的

当我们从终端执行行打包命令时,经历了如下过程,我画了一个核心流程图(顺着步骤顺序整体过一遍比较清晰):

image.png

详细整体打包流程:

  1. 判断是否安装webpack-cli或者webpack-command,若已安装进入2,否则报错提示

  2. 获取到webpack的配置参数options,将参数传给webpack,拿到compiler实例,调用compiler.run()

  3. 注册一些钩子后调用compiler.compile()开始构建,创建 compilation对象,用于存储这一次编译过程的所有数据

  4. 通过compiler.hooks.make.callAsync()触发make钩子, singleEntryPlugin对make进行了注册事件,调用compilation.addEntry开始构建模块,直到所有模块创建结束(各种loader在此阶段执行)

    4.1. this.hooks.make.callAsync触发make钩子,执行 SingleEntryPlugin(有make的事件注册),调用了 Compilation.addEntry方法,添加入口模块,开始编译&构建

    4.2. addEntry 中调用 _addModuleChain,将模块添加到依赖列表中,并编译模块*

    4.3. 在 buildModule 方法中,通过module.build调用了 NormalModule.build,创建模块之时会调用 runLoaders(单独的run-loader库)

    4.4 执行 runLoader,通过JavaScriptParse解析,利用 acorn编译生成 AST,分析文件的依赖关系添加到依赖模块并重复上述过程

  5. 完成所有依赖及loader,触发hooks.seal钩子生成 chunks,对 chunks进行一系列的plugin优化操作,合并runtime代码和业务代码并生成要输出的代码。

  6. 资源准备就绪后触发hooks.emit钩子,webpack会遍历compilation.assets, 生成所有文件,然后触发afterEmit表示资源输出完成,最后触发hooks.done,结束构建流程。

以上就是webpack整个打包的核心流程,花费了不少精力,感谢点赞支持哟~

下一篇继续分析loader是如何触发和执行的 juejin.cn/post/700239…