这是我参与11月更文挑战的第6天
异步执行AsyncQueue下的_ensureProcessing()方法执行时
首先会遍历this._queued,但此时this._queued.length = 0
其次会遍历this.children,此时this.children.length = 3
this._children为三个AsyncQueue
- _name为addModule的AsyncQueue, 开始它的_queued.length=0
- _name为factorize的AsyncQueue, 开始它的_queued.length=入口个数
- _name为build的AsyncQueue, 开始它的_queued.length=0 this.children的每一个AsyncQueue下面有一个_queued,即this.children[0]._queued
首先会处理_name是factorize的AsyncQueue
this.children[1]._queued.length=2
this.children[1]._queued是两个AsyncQueueEntry
所以执行_ensureProcessing()方法,首先会遍历 this.children[1]._queued,执行_startProcessing方法
由于AsyncQueued的this._parallelism默认是1;所以并不会两个都执行 而是执行一个入口的factorize,再执行该入口的addModule; 接着执行下一个入口的factorize,在执行addModule
factorize是分解的意思
_startProcessing()调用this.Processor,此时的Processor的name是 'bound _factorizeModule'
_ensureProcessing(entry){
this.processor(entry.item)
}
其次会处理_name是addModule的AsyncQueue
factorize和addModule的默认处理顺序是处理完一个入口的factorize和addModule,再处理下一个入口的factorize和addModule; 所有入口的factorize和addModule都处理完成后,再处理build
最后处理_name是build的AsyncQueue,_name是addModule的AsyncQueue处理完后,它的_queued.length=入口的个数
此时的Processor的name是 'bound _addModule'
name为factorize的异步队列的执行过程
- Compilation类 的_factorizeModule()方法内部调用了NormalModuleFactory的create方法
function _factorizeModule(){
factory.create()
}
- NormalModuleFactory类 的create()方法中触发了自己的beforeResolve钩子
- NormalModuleFactory类 的beforeResolve钩子执行完成后触发了自己的factorize钩子
function create(){
this.hooks.beforeResolve.callAsync(resolveData, (err, result) => {
this.hooks.factorize.callAsync(resloveData, (err, module))
})
}
ExternalModuleFactoryPlugin 插件注册了normalModuleFactory的factorize钩子
function apply(normalModuleFactory){
normalModuleFactory.hooks.factorize.tapAsync("ExternalModuleFactoryPlugin",(data,callback)=>{
fuction handleExternal(){
callback()
}
handleExternal()
})
}
NormalModuleFactory自己注册了自己的factorize钩子 NormalModuleFactory的factorize钩子执行完成后触发自己的reslove钩子
this.hooks.factorize.tapAsync({}, ()=>{
this.hooks.reslove.callAsync()
})
-
NormalModuleFactory自己注册了自己的reslove钩子
-
reslove钩子内部调用了defaultResolve()方法
-
defaultResolve()方法调用了resolveResource()方
-
resolveResource()方法调用了Resolver类的resolve()方法
-
resolve()方法调用了doResolve()方法
-
Resolver的doResolve()方法内部触发了自己的resolve钩子
-
ResolverCachePlugin插件注册了Resolver的resolve钩子
-
DescriptionFileFlugin插件注册了Resolver的resolve钩子
用来处理描述文件即package.json文件
-
NextPlugin插件注册了Resolver的resolve钩子
-
AliasFieldPlugin插件注册了Resolver的resolve钩子
先读取package.json文件中的browser的配置 browser配置:定义npm包在browser环境下的入口文件
-
ConditionalPlugin插件注册了Resolver的resolve钩子
-
RootsPlugin插件注册了Resolver的resolve钩子
-
FileExistsPlugin插件注册了Resolver的resolve钩子
const file = requet.path
fs.stat(file, )
// CachedInputFileSystem文件
class CacheBackend {
provide(path, options, callback){
let cacheEntry = this._data.get(paeh)
if(cacheEntry !== undefined){
}
this._provider.call(this._providerContext, path, (err, path) => {
this._storeResult(path, err, result)
})
}
}
//graceful-fs/polyfills.js
function statFix(){
}
// <node_internal>/fs.js
function stat(path, options = {bigit:false}, callback){
}
newStack = [
"resolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"parsedResolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"describedResolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"normalResolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"relative: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"describedRelative: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"rawFile: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"file: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"finalFile: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"existingFile: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
"resolved: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js"
]
将入口文件及其相关联文件和路径加入到AsyncQueue._queued中,然后遍历AsyncQueue._queued
AsyncQueue._queued = [
"D:\\code\\web_learn\\webpack\\demo\\src\\app.js",
"D:\\code\\web_learn\\webpack\\demo\\src",
"D:\\code\\web_learn\\webpack\\demo",
"D:\\code\\web_learn\\webpack",
"D:\\code\\web_learn",
"D:\\code",
"D:\\",
"D:\\code\\web_learn\\webpack\\demo\\package.json",
"D:\\code\\web_learn\\webpack\\demo\\src\\search.js",
]
name为addModule的异步队列的执行过程
_startProcessing(entry){
this._processor(entry.item, (e,r) => {
this._handleResult(entry, e, r)
})
}
调用Compilation的_addModule()
// module大致的样子
module = {
rawRequest: './src/app.js',
request: 'D:\\code\\web_learn\\webpack\\demo\\src\\app.js',
resource: 'D:\\code\\web_learn\\webpack\\demo\\src\\app.js',
userRequest: 'D:\\code\\web_learn\\webpack\\demo\\src\\app.js',
type: 'javascript/auto'
}
function _addModule(module, callback) {
const identifier = module.identifier
//判断是否已经添加
const alreadyAddedModule = this._modules.get(identifier)
if(alreadyAddedModule){
return callback(null, alreadyAddedModule)
}
// 从缓存中读取
this.modulesCache.get(identifier, null, (err, cacheModule) => {
if(cacheModule) {
cacheModule.updateCacheModule(module)
module = cacheModule
}
this._modules.set(identifier, module)
this.modules.add(module)
callback(null,module) // 执行_handleResult
})
}
执行AsyncQueue类中的_handleResult()
执行Compilation下面的handleModuleCreation下面的this.factorizeModule下面的 addModule(newModule)
执行Compilation下面的_handleModuleBuildAndDependencies 下面的 this.buildModule
Compilation的buildQueue新增newModule:this.buildQueue.add(module, callback)
接着将其他的module添加到buildQueue中
所有module加入到buildQueue后,name为build的AsyncQueued的_queued.length = 2
所以接着遍历这个_name为build的AsyncQueue的_queued
name为build 的异步队列的执行过程
此时_this.processer为 bound _buildModule
执行Compilation类下的_buildModule()
- 首先判断该module是否需要build
_buildModule(module, callback) {
module.needBuild({}, (err, needBuild) => {
if(needBuild){
this.hooks.buildModule.call(module)
this.buildModules.add(module)
module.build()
}
})
}
- 开始构建module
// NormalModule.js
function build(){
this._doBuild()
}
_doBuild(){
}
经过漫长的前置处理,终于开始了真正的处理流程了,请查看 webpack运行过程(4)核心操作