webpack源码探索(二)

174 阅读2分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

前言

我们书接上回,继续进行webpack的源码学习。回顾一下上一章的内容,我们看到webpack初始化的时候,执行了runCli方法,进行了一系列webpack-cli的操作,然后又回到了webpack的源码中。

源码学习

webpack 方法

webpack方法接收两个参数:options和callback。

options是webpack-cli中对webpack命令参数的整合。而如果传入callback的时候,会在webpack打包成功或者失败的时候,将结果或者错误信息传入callback并执行。

    compiler.run((err, stats) => {
        compiler.close(err2 => {
            callback(err || err2, stats);
        });
    });

这里有点需要提一下,不知道大家有没有写过或者见过webpack手动调用的实现,通过手动创建webpack并执行run方法。大体代码如下:

webpack(config).run((err, stats) => {
    return err ? reject(err) : resolve(stats);
})

这个run方法中传入的callback其实跟compiler中接收的callback是同一个回调方法。

在这个方法中,我们可以了解到一个知识点:如果执行webpack的时候,传入了--watch,或者在webpack的配置文件中配置了watch:true的时候,说明webpack打包的时候开启了观察模式。

create方法

在create方法中,首先做了options参数的校验。然后做了options参数的处理。通过这个方法我们可以发现,webpack通过判断options的数据类型来判断webpack是单配置还是多配置。如果options是数组类型,通过调用createMultiCompiler方法来处理;如果options是对象类型通过调用createCompiler方法来处理。

在createMultiCompiler中,通过遍历options调用createCompiler方法来处理每一组配置。

    const compilers = childOptions.map(options => createCompiler(options));

createCompiler方法

在createCompiler方法中,首先会对options参数进行格式化处理(如果没有传入options,则会完全采用webpack内置的配置),然后通过通过实例化Compiler方法来创建webpack编译器,最后有一点比较特殊的是对plugin插件进行了挂载处理。

这里有一点比较奇怪的地方,按照常理createCompiler方法中,最终目的就是创建compiler,但是,在最后的时候做的是plugin插件处理,而且通过这里我们可以发现plugins配置的方式,是以数组的形式配置的。

    for (const plugin of options.plugins) {
        if (typeof plugin === "function") {
            plugin.call(compiler, compiler);
        } else {
            plugin.apply(compiler);
        }
    }

在这个方法中,我们初步接触到了tapable,也就是大家常说的webpack的钩子。

    compiler.hooks.environment.call();
    compiler.hooks.afterEnvironment.call();
    ...
    compiler.hooks.initialize.call()

结语

接下来就是webpack的核心——Compiler,在Compiler的实体类中我们就会接触到webpack打包编译的核心流程。在理解Compiler之前,需要理解一下tapable。

好了,这一期的源码分析到这里就结束了。欢迎小伙伴们在下方留言讨论。