zoukankan      html  css  js  c++  java
  • .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);

      这个函数有点长,下一节再来讲解。

  • 相关阅读:
    js——获取指定日期的前7天连续日期
    一个div自动充满当前屏幕的解决方法
    Cookie和Session
    Web服务器和浏览器间的工作原理
    软件测试基础概念
    K短路的几种求法
    ID字体
    搭建GitLab的Hexo博客记录
    项目selfcmp开发学习
    牛顿迭代法学习笔记
  • 原文地址:https://www.cnblogs.com/QH-Jimmy/p/8022935.html
Copyright © 2011-2022 走看看