.3-浅析webpack源码之预编译总览
写在前面:
本来一开始想沿用之前vue源码的标题:webpack源码之***,但是这个工具比较巨大,所以为防止有人觉得我装逼跑来喷我(或者随时鸽),加上浅析二字,以示怂。
既然是浅析,那么案例就不必太复杂,所以继续按照之前vue源码,以最简单形式进行源码分析,如下:
配置文件config.js:
module.exports={
entry:'./entry.js',
output:{
filename:'output'
}
}
入口文件entry.js:
console.log('entry');
执行命令为:
node webpack --config config.js
不摸鱼了,开始正式进入源码,惯例上图:
之前简单讲解了webpack.cmd的内容,可以发现在正常进行webpack打包之前,会调用bin文件夹的webpack.js文件,这一节就看一下这个文件做了什么,经过简单整理,源码如下:
var path = require("path");
// 优先使用当前路径版本的webpack.js
try {
var localWebpack = require.resolve(path.join(process.cwd(), "node_modules", "webpack", "bin", "webpack.js"));
if(__filename !== localWebpack) {
return require(localWebpack);
}
} catch(e) {}
// 引入yargs框架
var yargs = require("yargs")
.usage("字符串...");
// 配置
require("./config-yargs")(yargs);
var DISPLAY_GROUP = "Stats options:";
var BASIC_GROUP = "Basic options:";
yargs.options({
"json": {
type: "boolean",
alias: "j",
describe: "Prints the result as JSON."
},
// ...
// 各种配置...
});
// 解析命令行参数并执行回调函数
// 正常情况下err为null output为空字符
yargs.parse(process.argv.slice(2), (err, argv, output) => {
// 报错信息
if(err && output) {
// ...
}
// 输出帮助或版本信息
if(output) {
// ...
}
// 这里对配置文件进行转换与合法性检测
var options = require("./convert-argv")(yargs, argv);
// argv的参数二次处理
// 暂时无视
function ifArg(name, fn, init) {
// ...
}
// 解析配置文件
function processOptions(options) {
// 当前配置文件是一个Promise时
if(typeof options.then === "function") {
options.then(processOptions).catch(function(err) {
console.error(err.stack || err);
process.exit(1); // eslint-disable-line
});
return;
}
// 大量的ifArg(...)
// 获取webpack主函数
var webpack = require("../lib/webpack.js");
Error.stackTraceLimit = 30;
var lastHash = null;
var compiler;
try {
// 编译
compiler = webpack(options);
} catch(err) {
// error
}
// ...编译后回调 暂时不管
}
// 执行上面的函数
processOptions(options);
});
源码说长也不长,可以分为五大块:
1、引入yargs框架并进行配置
2、使用yargs解析命令并调用回调函数
3、进行配置文件参数转换与合法性检测
4、引入webpack主函数进行编译
5、编译完成后调用对应的回调函数
其中yargs框架是一个命令行框架,具体内容请自行查阅,这里不会做更多介绍,因此源码内容会按顺序跳着讲。
首先是一个小try/catch语句:
// Local version replace global one
try {
var localWebpack = require.resolve(path.join(process.cwd(), "node_modules", "webpack", "bin", "webpack.js"));
if(__filename !== localWebpack) {
return require(localWebpack);
}
} catch(e) {}
其实注释已经讲明了这个代码块的作用,这里稍微详细再说几点。
process是node中的一个全局对象,而process.cwd()方法可以获取到当前进程的绝对路径,测试如图:
所以第一行赋值语句会尝试获取./node_modules/webpack/bin/webpack,js文件并进行调用,将结果赋给localWebpack。
而__filename是当前指令文件的详细绝对路径,在默认的node webpack *指令中,一般情况我们都会配置环境变量,所以这个webpack指向全局的webpack,而__filename也是全局的webpack.js路径。
因此,if判断就是优先使用当前路径的webpack.js,如果不存在,就使用全局的webpack来进行编译解析。
接下来的几块内容全是yargs的配置,这里就不细看了,直接进入yargs.parse函数:
yargs.parse(process.argv.slice(2), (err, argv, output) => {
// ...
})
前面提到过process是node的全局对象,argv是它的一个属性,主要处理命令参数,可以简单打印看一下内容:
在什么也不做的时候,会返回一个数组,其中第一个元素默认为node.exe路径。
这里创建一个JS专门打印process.argv:
// entry.js
console.log(process.argv);
然后执行下列命令:
node entry 1 2 3
结果如图:
可以看到,传入命令的参数是从第三个开始依次展开,所以yargs.parse的第一个参数排除了argv数组的前两个,只传命令参数。
yargs的parse方法会负责收集并管理参数,在执行成功后会调用后面的函数,回调函数有三个参数,分别为:
1、err => 解析过程中的错误信息
2、argv => 参数管理对象
3、output => 输出到终端的文本
如果正常解析,err为null,而output为空字符。
这里可以观察一下argv的内容,在源码中打印结果如图:
这只是一部分属性的截图,对象中的第一个_保存了传进来的参数,由于直接运行的node webpack --config *,后面没有带参数,所以这里是个空数组。
而其余大量的属性都是在之前配置中添加的,比如说前面的4个:help、h、version、v,来自于config-yarg.js文件,源码如下:
module.exports = function(yargs) {
yargs
.help("help")
.alias("help", "h")
.version()
.alias("version", "v")
.options(
// 更多配置...
)
}
这个配置不是关心的重点,暂时没必要去看。
接下来是convert-argv函数,负责对配置对象转换并返回:
var options = require("./convert-argv")(yargs, argv);
这个函数有点长,下一节再来讲解。
.3-浅析webpack源码之预编译总览的更多相关文章
- .9-浅析webpack源码之NodeEnvironmentPlugin模块总览
介绍Compiler的构造比较无趣,不如先过后面的,在用到compiler的时候再做讲解. 这一节主要讲这行代码: // 不管这里 compiler = new Compiler(); compile ...
- .12-浅析webpack源码之NodeWatchFileSystem模块总览
剩下一个watch模块,这个模块比较深,先大概过一下整体涉及内容再分部讲解. 流程图如下: NodeWatchFileSystem const Watchpack = require("wa ...
- .17-浅析webpack源码之compile流程-入口函数run
本节流程如图: 现在正式进入打包流程,起步方法为run: Compiler.prototype.run = (callback) => { const startTime = Date.now( ...
- Spring Boot 2.0系列文章(五):Spring Boot 2.0 项目源码结构预览
关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/04/15/springboot2_code/ 项目结构 结构分析: Spring-boot-pr ...
- 从Webpack源码探究打包流程,萌新也能看懂~
简介 上一篇讲述了如何理解tapable这个钩子机制,因为这个是webpack程序的灵魂.虽然钩子机制很灵活,而然却变成了我们读懂webpack道路上的阻碍.每当webpack运行起来的时候,我的心态 ...
- Android之源码之模块编译和调试
Android之源码之模块编译调试 (一) 进行源码模块修改进行编译的调试 1.首先是从git或者svn上拉一套完整的工程下来,然后全编一下,一般这个时间比较长,大概会得2,3个小时左右, 2,编译成 ...
- 【原创】从零开始学SpagoBI5.X源码汉化编译
从零开始学SpagoBI5.X源码汉化编译 一.新建Tomact Server 服务器并配置测试1.文件-新建-其他-过滤server-服务类型选择Tomact V7.0 Server2.根据需要修改 ...
- .30-浅析webpack源码之doResolve事件流(1)
这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...
- 51ak带你看MYSQL5.7源码2:编译现有的代码
从事DBA工作多年 MYSQL源码也是头一次接触 尝试记录下自己看MYSQL5.7源码的历程 目录: 51ak带你看MYSQL5.7源码1:main入口函数 51ak带你看MYSQL5.7源码2:编译 ...
随机推荐
- 第7章 "敏捷+"项目管理
7.1 导入敏捷项目管理的步骤 1.导入敏捷的步骤 (1).培训 (2).教练与引导 (3).内化 2.敏捷混合型模式 7.2 项目启动与敏捷合同 1.敏捷项目启动 2.敏捷签约模式 在传统项目管 ...
- <string.h>的学习
感觉学习代码库最好的方法就是运行一下. 下面附上结果和示例代码 #include <stdio.h> #include <string.h> int main(){ const ...
- 探索基于.NET下实现一句话木马之asmx篇
0x01 前言 上篇介绍了一般处理程序(ashx)的工作原理以及实现一句话木马的过程,今天接着介绍Web Service程序 (asmx)下的工作原理和如何实现一句话木马,当然介绍之前笔者找到了一款a ...
- Html Agility Pack解析Html(C#爬虫利器)
有个需求要写网络爬虫,以前接触过一个叫Html Agility Pack这个解析html的库,这次又要用到,然而发现以前咋用的已经不记得了,现在从头开始记录一下使用过程. Html Agility P ...
- 【BZOJ2002】 [Hnoi2010]Bounce 弹飞绵羊
BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊 Solution 很早以前写的一道分块题,最近在搞LCT,又做了一遍. 1.LCT做法 看到这种动态修改,想下LCT怎么维护. 修改操作就 ...
- AJPFX:什么是止盈?什么是止损?
在您进行外汇交易后,会碰到Take Profit(止盈)和 Stop Loss(止损)这两个词,均是用作控制风险的工具. 止盈(Take Profit):当单子达到预期的获利价格时锁定盈利.当订单在盈 ...
- dapper视频
dapper是dotnet下的一种小巧快捷的ORM框架,本视频主要讲解了dapper的多库使用,以及常见的操作,如:对象查询.多集合查询,关联查询等,添加.修改.删除等. 视频地址:https://w ...
- iOS-项目开发1
FFPageControl 由于UIPageControl不能设置图片,而在实际开发中又经常遇到需要使用图片的情况,故仿照系统UIPageControl,重写了FFPageControl,以支持图片的 ...
- 【Junit4】:要点随笔
1. 引入Junit4的Maven依赖 <dependencies> <dependency> <groupId>junit</groupId> < ...
- 基于iview的后台管理
年前由于时间紧迫,原本使用iview技术开发后台管理系统的大神另有任务,我中途接手该项目,此前对于iview一无所知的我是一脸的懵逼,好在后台管理的整体框架大神已经搭建好了,而我之前对vue也有一定的 ...
