前言
webpack是目前最流行的前端构建工具,了解并熟悉它是必要的。2019年初定下了阅读Vue和Webpack的源码计划,Vue的源码阅读大致完成,前段时间稍微繁忙些,2019年最后一个月才开始着手阅读webpack的源码,初步完成年前的计划。
本系列文章的webpack版本是3.4.0。
流程逻辑
首先查看webpack源码目录下package.json文件,主要关注以下的点:
"bin": {
"webpack": "./bin/webpack.js"
},
"main": "lib/webpack.js",
"name": "webpack"
相关字段说明:
- bin字段定义了webpack命令对应的可执行文件的位置
- main字段指定了加载的入口文件
main字段的默认值是模块根目录下面的index.js,例如上面的配置require(‘webpack’)就会加载lib/webapck.js文件
这里看webpack命令对应的文件即bin/webpack.js,主要流程有:
本地webpack判断
var localWebpack = require.resolve(path.join(process.cwd(), "node_modules", "webpack", "bin", "webpack.js"));
if(__filename !== localWebpack) {
return require(localWebpack);
}
判断当前目录下node_module/webpack/bin/webpack.js是否与当前执行的webpack命令的文件地址是否一致。如果不一致就会返回当前目录下node_module/webpack/bin/webpack.js,保证本地webpack覆盖全局webpack。
yargs相关操作逻辑
yargs是Nodejs命令行工具,该模块就是用来解决如何处理命令行的参数的,lib/webpack.js文件涉及模块有相关参数有:
- usage():生成用法格式相关的帮助信息
- help():生成帮助信息
- alias():定义别名
- options():允许将所有的配置写入配置对象
- argv对象:用来读取命令行参数
config-yargs.js文件主要暴露出函数用于处理相关命令行命令的支持,主要有:
module.exports = function(yargs) {
yargs
.help("help")
.alias("help", "h")
.version()
.alias("version", "v")
.options({
// 相关参数名配置
"config": {
type: "string",
describe: "Path to the config file",
group: CONFIG_GROUP,
defaultDescription: "webpack.config.js or webpackfile.js",
requiresArg: true
}
})
定义-v、-h、–help,并定义相关webpack命令的参数,例如config参数:
webpack --config webpack.config.js
convert-argv.js文件主要是结合yargs.options转换命令行参数,生成最后的options选项对象即webpack所有配置项。
processOptions函数
processOptions函数主要的处理是判断相关参数是否存在并依据判断去赋值相关字段值,其中最核心的逻辑是:
var webpack = require("../lib/webpack.js");
try {
compiler = webpack(options);
} catch(e) {
// 相关报错处理
}
if(argv.progress) {
var ProgressPlugin = require("../lib/ProgressPlugin");
compiler.apply(new ProgressPlugin({
profile: argv.profile
}));
}
function compilerCallback(err, stats) {}
if(firstOptions.watch || options.watch) {
var watchOptions = firstOptions.watchOptions || firstOptions.watch || options.watch || {};
compiler.watch(watchOptions, compilerCallback);
console.log("\nWebpack is watching the files…\n");
} else {
compiler.run(compilerCallback);
}
从上面的代码中年可以看出3处主要逻辑:
- 导入lib/webpack.js,即导入webpack函数,然后执行webpack函数返回Compiler对象
- 定义progress参数会调用ProgressPlugin插件会调用Compiler对象的apply方法
- 定义watch参数则会调用Compiler对象的watch方法
- 如果没有定义watch则会直接调用Compiler对象的run方法,一旦调用run方法就会开始编译
总结
webpack的初始化参数涉及到的命令行参数等比较多,webpack源码分析的系列文章关注点是整个webpack的流程以及流程中主要点。
初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数对象options
下篇文章的关注点在:
- webpack函数执行
- Compiler对象run方法执行开始编译