webpack中的Loader在编译过程中是如何应用的

119 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

按照顺序提取其中一部分关键的环节。如下图:

image-20220825152728257.png 首先要注意的是this.hook.make.callAsyncthis.hook.make.tapAsync 这种用法几乎涉及到webpack的各个部分,它使用钩子来串联业务的不同环节。

在上图中对于每个方法所在的文件路径都进行了标注,它的具体位置是工程根目录下的node_modules文件夹。这里所提取的环节全部都是webpack下的,需要注意的是,它在过程中还会涉及到其他的模块。比如 tapablewebpack-sourcewebpack-clistyle-loadercss-loader等。

Compiler.js中可以看到 this.hooks.make 对应的是:

image-20220825153345197.png 对于钩子的用法在前面tapable的文章中介绍过。简单理解为它是一种事件监听的消息机制。tap是订阅者,而call是监听者。监听者监听消息,发布给订阅者。所以执行到 this.hook.make.callAsync的时候,它会调用 this.hook.make.tapAsync的回调函数。这里需要强调的时,callAsync 执行的是 tapAsync的回调。所以,在 this.hook.make.callAsync 执行之前,会先执行 this.hook.make.tapAsync ,把订阅者给放到 taps 的数组中。如下:

image-20220825153734216.png 这个方法对于掌握webpack中针对钩子的使用过程非常重要。

这里在开始的时候调用了EntryPlugin,是因为它处理的是对应于入口文件的逻辑。而这个入口文件配置与webpack.config.js 中的 entry,也就是如下内容:

...
module.exports={
    entry:'./main.js',
  ...
}

当在Compilation.js 下的 _addEntryItem 中执行完 this.hooks.addEntry.cal(entry,options) 之后,会发现在终端中的进度信息展示如下:

10% building 0/1 entries 0/0 dependencies 0/0 modules

image-20220825162247090.png

这就说明当前的操作正在构建入口配置的信息。

然后进入到构建阶段,构建过程中针对模块的加载,不同模块钩子的配置,构建后执行 runLoaders,这里的runLoaders会调用 loader-runner 中的 runLoaders,如下:

image-20220825172934366.png 这其中关键的一步是 processResource,如下:

image-20220825173042645.png 执行后回调到 NormalModule.js 下的 runLoaders 下的 processResource 中,如下:

image-20220825173428702.png 通过 hooks.readResource.for 获取对应的钩子,读取文件,如下:

image-20220825173609414.png