25_Webapck原理
Webpack源代码解析
webpack其实也就是一个函数的调用,返回一个Compile的对象,再调用Compile的run方法就可以完成项目的构建
那么我们肯定是先要从webpack这个函数去理解它在构建的过程中都做了些什么
如果我们没有传入callback那么他就会执行else中的代码,首先是create函数
那么我们核心的代码就在createCompiler函数中
插件的执行是贯穿于webpack的整个生命周期的,webpack当中很多的东西其都是插件,比如entry,他会把它转成插件
转换的过程就在WebapackOptionsApply当中
它注册插件的目的就是将compiler对象传入插件的apply函数中去,在apply函数中监听compiler对象的hooks,那么在webpack执行到某一个生命周期的时候compiler会去回调hooks
那么我们再看看hooks是什么东西
我们肯定先看打开Compiler这个类
你会发现有很多的hooks(钩子),实际上他们是用了一个tapable的库有兴趣的可以去看
我们的插件都会去调用它的apply传入compiler,apply的函数中都会去执行compiler.hooks.xxx(钩子),如其中一个hooks.xxx.tap('xxx',回调)这个注册的事件会在webpack编译的某个生命周期里面compiler.hook.xxx.call('xxx')去回调
那么我们真正构建的时候是去调用compiler的run方法
接下来分析run方法做了什么事情
编译的过程在this.compile(onCompiled)中,onCompiled是没有错误的回调函数
打开apply函数
它会调用EntryOptionPlugin的静态方法applyEntryOption
我们再打开applyEntryOption
打开EntryPlugin的apply方法
那么这个hooks到make阶段的时候回调就开始执行了,并且把compilation传入
打开这个_addEntryItem私有函数
他的本质就是想调用addModuleTree
根据当前模块,把他加入到模块树中去
处理这个模块并且把他创建
最终会调用factorizeModule方法
加入到队列中去
最终的执行都是按照队列的方式进行执行的
他将处理好的模块传入到newModule中去
看看addModule做了什么
把模块加入到了modulequeue中去
当监听到某个hooks后他会去回调callback
构建模块
把即将构建的模块又加入到buildqueue中去了
在我们buildqueue中其实已经有很多我们加进去的模块了
而这个队列中是有一个处 理的方法的
具体的构造模块其实就是在这里
调用_buildModule的时候就开始真正的构建我们的模块了
打开build方法
其实打开的是一个子类
点击这里
找到实现类
点开doBuild
resource是即将要处理的资源
loaders是要应用的loaders
processResult是之前在上面定义的函数(处理结果的函数)
我们最主要的就是看它回调的这个callback
这个callback是在build函数中传入的
this.parser.parse最主要的就是解析js代码,这个parser是一个类,但是是个抽象类,他的实现类是javaScriptParser,但是在处理的时候是使用了acorn库,最主要的就是分析当前模块是否依赖了其他的模块,如果依赖了,他还是会继续回到runLoader函数中去,继续去处理他所依赖的模块,依次处理
如果ast有值的话他会去处理ast,或者去调用source函数得到结果交给parsser的parse函数去处理
当解析完成之后他就会来到Compilation中的seal(封存)方法中
把我们解析好的模块封存到chunk中去(把我们解析好的模块分别放到哪些chunk中去)
最终解析出来的数据其实是放到compilation.assets对象中去,但是他在模块真正转成js文件之前是要进行优化的(optimization)
模块->chunk->optimization->compilation.assets
有特别多的处理代码,我们一直往下翻到codeGeneration
往下找里面有一个函数叫 createChunkAssets
往下翻
输出资源 source中有_source就是要输出的内容
目的就是将资源放到compilation对象中去
this就是compilation
当我们做完这些之后就要去做我们的回调过程了
这个callback是之前传入进来的,经过不断的追溯,最终是在调用seal函数的地方(Compiler的compiler方法中)
他调完之后还会调用一个afterCompile的hook,afterCompile的hook调用完成之后还接着会调用callback,那么这个callback就是compile函数的参数,compile是在run方法中调用的所以我们找到run方法
当我们调用完成onCompiled之后他接着就会调用emitRecords去输出里面的资源