「这是我参与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中,好的,我们今天的代码分析就到这里了,明天继续后续代码的分析。
如果有任何问题,欢迎小伙伴们进行留言讨论。