webpack运行过程(3)

433 阅读3分钟

这是我参与11月更文挑战的第6天

异步执行AsyncQueue下的_ensureProcessing()方法执行时

首先会遍历this._queued,但此时this._queued.length = 0

其次会遍历this.children,此时this.children.length = 3

this._children为三个AsyncQueue

  1. _name为addModule的AsyncQueue, 开始它的_queued.length=0
  2. _name为factorize的AsyncQueue, 开始它的_queued.length=入口个数
  3. _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()

  1. 首先判断该module是否需要build
_buildModule(module, callback) {
    module.needBuild({}, (err, needBuild) => {
         if(needBuild){
             this.hooks.buildModule.call(module)
             this.buildModules.add(module)
             module.build()
         }
        
    })
   
}
  1. 开始构建module
// NormalModule.js
function build(){
    this._doBuild()
}

_doBuild(){

}

经过漫长的前置处理,终于开始了真正的处理流程了,请查看 webpack运行过程(4)核心操作