You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// lib/EntryOptionPlugin.jsconstitemToPlugin=(context,item,name)=>{if(Array.isArray(item)){returnnewMultiEntryPlugin(context,item,name);}returnnewSingleEntryPlugin(context,item,name);};module.exports=classEntryOptionPlugin{/** * @param {Compiler} compiler the compiler instance one is tapping into * @returns {void} */apply(compiler){compiler.hooks.entryOption.tap("EntryOptionPlugin",(context,entry)=>{if(typeofentry==="string"||Array.isArray(entry)){itemToPlugin(context,entry,"main").apply(compiler);}elseif(typeofentry==="object"){for(constnameofObject.keys(entry)){itemToPlugin(context,entry[name],name).apply(compiler);}}elseif(typeofentry==="function"){newDynamicEntryPlugin(context,entry).apply(compiler);}returntrue;});}};
在【webpack进阶系列】核心原理与流程中我们顺着webpack的核心脉络走了一遍
run
的流程,本篇我们详细读一下webpack如何从入口entry找到所有的依赖,并转为module的总览
下图为本篇文章的总览流程图
从入口开始,初始化
Compiler
控制整个webpack的编译流程,它的生命周期中暴露了很多方法,如run,make,compile,finish,seal,emit
等,Compiler
中会实例化Compilation
,它负责把所有的文件构建处理成module,一个Compiler
周期内会反复触发Compilation
实例无论入口文件是什么,都要从
compilation.addEntry
开始,执行_addModuleChain
,将入口文件加入需要编译的队列中,将队列里的文件依次处理,通过import/require
等方法依赖的文件也会通过addModuleDependencies
被添加到编译队列中,当整个编译队列完成时,从文件到module的转换就完成了编译队列
编译队列的控制是由
Semaphore
(信号量)来完成的,它的代码量很少,先看下它的实现通过
this.available
来控制同时处理资源的并发数,默认100这里的并发概念只是代码中的并发,跟JS单线程并不是同一个概念
只对外暴露了
acquire(申请资源)
、release(释放资源)
两个方法申请资源成功则
this.available--
,可用资源减1,申请资源失败则把任务丢进等待编译的队列this.waiters
释放资源则
this.available++
,同时从等待队列中拿出最后一个任务,并在process.nextTick
后执行入口与模块工厂
通过webpack官网文档,可以看到入口
entry
可以有string
、[string]
、object
、function
等几种形式通过前面的文章,我们知道用户自定义的配置都在
WebpackOptionsApply.process(options, compiler)
中处理了,而对于入口的处理在EntryOptionPlugin
插件中这个插件的代码也很简单
string
->SingleEntryPlugin
array
->MultiEntryPlugin
function
->DynamicEntryPlugin
object
-> 遍历后,根据不同类型选择SingleEntryPlugin/MultiEntryPlugin
然后我们再观察一下这个三个插件
SingleEntryPlugin、MultiEntryPlugin、DynamicEntryPlugin
,它们都会做的两件事情1、注册
compilation
钩子,设置dependencyFactories
,在后面的module.create()
时候可以根据拿到正确的moduleFactory
,moduleFactory
有可能是normalModuleFactory
、multiModuleFactory
2、注册
make
钩子回调,在make
被触发时,调用compilation.addEntry() -> compilation._addModuleChain
开始编译工作这一部分的整个流程串起来如下图
compilation构建
进入
module.create
后,跟着断点走能够比较清晰的看到compilation
实例中modules
和modules.dependencies
中的数据变化,下面的流程图比较清晰的画出了几个函数方法的调用过程具体
runLoaders
和Parser.parse
部分的调用逻辑没有深入往下读,后续有时间再另写文章细读下一篇是封装生成chunk的流程解读,敬请期待
The text was updated successfully, but these errors were encountered: