webpack源码探索(一)

141 阅读2分钟

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

前言

之前就打算深入学习一下webpack源码,但是由于各种这样那样的原因一直拖延。这段时间正好空闲,所以重新捡起来开始撸一下。

准备工作

  • 从GitHub上获取webpack源码

  • vscode编辑器

源码学习

1. 入口文件

webpack.js文件中,一共有三个方法和一个核心逻辑:runCommand、isInstalled和runCli。

核心逻辑:先通过isInstalled判断webpack-cli是否安装,如果安装了,直接执行runCli命令;如果没有安装,则通过runCommand命令来进行webapck-cli的安装,安装成功之后再执行runCli命令。

  • isInstalled 方法

这个方法中的核心代码:dir !== (dir = path.dirname(dir)),通过webpack.js所在的目录向上递归寻找是否存在webpack-cli模块,直到找到webpack-cli模块或者根目录没有找到安装目录。

__dirname指向当前文件所在目录的目录名 E:\studyFiles\my-app\node_modules\webpack\bin, fs.statSync 返回 Stats 类,然后通过 Stats.isDirectory 方法来判断依赖是否安装。

do {
    try {
        if (
            fs.statSync(path.join(dir, "node_modules", packageName)).isDirectory()
        ) {
            return true;
        }
    } catch (_error) {
        ...
    }
} while (dir !== (dir = path.dirname(dir)));
  • runCommand 方法

这个方法中的核心代码:cp.spawn(command, args, { stdio: "inherit", shell: true })。通过node提供的child_process命令来执行安装命令,通过添加error和exit事件来监听命令的执行结果。如果安装依赖失败,那就执行reject方法抛出错误;如果安装依赖成功,那就执行resolve方法通知依赖安装成功,然后执行后续方法。

这个方法涉及到的小知识点:

  • 通过process.cwd命令,获取运行命令行所在的文件目录

  • 在执行 runCommand 方法之前有一个细节需要特别提一下,通过寻找根目录中是否存在yarn.lock或者pnpm-lock.yaml文件,来判断依赖管理工具使用的是yarn、pnpm和npm,然后动态的生成webpack-cli的安装命令。

  • spawn命令跟shell命令有点区别,命令内容以字符串列表的形式传入。例如:[ 'install', '-D', 'webpack-cli' ]

  • runCli 方法

在这个方法中,通过加载了 webpack-cli/bin/cli.js,调用 runCLI 方法。接下来在cli.js中,对命令行参数做了一系列的处理,然后在回到了webpack中进行打包构建。

2. webpack-cli中逻辑

在runCLI方法中先执行 new WebpackCLI() 来获取cli实例,然后在 constructor 中将 commander.program 挂载到了 this.program 上,然后执行 WebpackCLI 的 run 方法。

在run 方法里面执行了 commander 命令行,然后在 program.action 的回调中执行了 loadCommandByName 方法;在 loadCommandByName 中执行了 makeCommand 方法,然后回调中先通过 loadWebpack 方法加载了 webpack,然后执行了 runWebpack 方法。

再接下来又回到了webpack中,好的,我们今天的代码分析就到这里了,明天继续后续代码的分析。

如果有任何问题,欢迎小伙伴们进行留言讨论。