资讯专栏INFORMATION COLUMN

浅析webpack源码之入口函数webpack.js详解(四)

zone / 1336人阅读

摘要:我们看到引入了对进行分析是一个很大的文件,里面规定了我们随便看一段这是对你输入的规定的要求是是其实就是本下的这样写可以提取公用的配置,避免代码冗余一共行,其中就占了行接下里进入函数引入引入了,我们在搜索链接我们看到,在文档里这样的描述的用法

我们看到引入了

对webpack.js

const validateSchema = require("./validateSchema");
const webpackOptionsSchema = require("../schemas/WebpackOptions.json");
const webpackOptionsValidationErrors = validateSchema(
    webpackOptionsSchema,
    options
);

进行分析

webpackOptionsSchema是一个很大的json文件,里面规定了

我们随便看一段

{
"entry": {
      "description": "The entry point(s) of the compilation.",
      "anyOf": [
        {
          "$ref": "#/definitions/Entry"
        }
      ]
    },
    "externals": {
      "description": "Specify dependencies that shouldn"t be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on `output.libraryTarget`.",
      "anyOf": [
        {
          "$ref": "#/definitions/Externals"
        }
      ]
    },
    "loader": {
      "description": "Custom values available in the loader context.",
      "type": "object"
    }
}

这是对你输入options的规定

loader的type要求是object

$ref是 #/definitions/Externals其实就是本json下的definitions/Externals

这样写可以提取公用的配置,避免代码冗余

一共2100行,其中definitions就占了1800行

接下里进入validateSchema.js函数

//引入ajv
const Ajv = require("ajv");
const ajv = new Ajv({
    errorDataPath: "configuration",
    allErrors: true,
    verbose: true
});

引入了ajv,我们在gihub搜索ajv 链接

我们看到,在文档里这样的描述的用法

var Ajv = require("ajv");
var ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
var validate = ajv.compile(schema);
var valid = validate(data);
if (!valid) console.log(validate.errors);

这个逻辑比较简单

new一个 ajv,调用方法 ajv.compile(schema),schema就是你规定的对象

validate是返回的一个函数

把要验证的数据传入参数,如果有错误会记在valid里

const validateObject = (schema, options) => {
    const validate = ajv.compile(schema);
    const valid = validate(options);
    return valid ? [] : filterErrors(validate.errors);
};

很显然,webpack也是这样使用的,如果有错误,调用filterErrors,又对错误进行了一层包装


validate函数实在是太长了就不贴了,对ajv有兴趣的可以研究研究,输入什么,输出的错误会又怎样的格式输出等

这个不影响主线,我们接着往下读

// 如果有错误就交给WebpackOptionsValidationError对象处理
if (webpackOptionsValidationErrors.length) {
    throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
}

接下来

let compiler;
//多配置
if (Array.isArray(options)) {
    compiler = new MultiCompiler(options.map(options => webpack(options)));
} else if (typeof options === "object") {
    options = new WebpackOptionsDefaulter().process(options);

    compiler = new Compiler(options.context);
    compiler.options = options;
    new NodeEnvironmentPlugin().apply(compiler);
    if (options.plugins && Array.isArray(options.plugins)) {
        for (const plugin of options.plugins) {
            if (typeof plugin === "function") {
                plugin.call(compiler, compiler);
            } else {
                plugin.apply(compiler);
            }
        }
    }
    compiler.hooks.environment.call();
    compiler.hooks.afterEnvironment.call();
    compiler.options = new WebpackOptionsApply().process(options, compiler);
} else {
    throw new Error("Invalid argument: options");
}
options = new WebpackOptionsDefaulter().process(options);`

我们走单配置即传值为对象的时候,
传进去一个options 输入一个options
很明显是是给options添加默认配置
就是给options多挂在几个默认属性,至于怎么添加的,添加了什么,不是重点,感兴趣的可以读读WebpackOptionsDefaulter函数

大部分的复杂架构,无论是vue和react,都会对你传入的对象作出相应的默认处理,接着往下

        // 调用Compile,传入当前文件路径
        compiler = new Compiler(options.context);
        // compiler对象上挂载属性options
        compiler.options = options;
        // compiler对象上挂载属性options
        //给compiler加载node环境
        new NodeEnvironmentPlugin().apply(compiler);
        //options.plugins存在且为数组
        if (options.plugins && Array.isArray(options.plugins)) {
            for (const plugin of options.plugins) {
                if (typeof plugin === "function") {
                    plugin.call(compiler, compiler);
                } else {
                 //plugin是对象怎么会有改变this的apply方法?后续代查
                    plugin.apply(compiler);
                }
            }
        }
        compiler.hooks.environment.call();
        compiler.hooks.afterEnvironment.call();
        compiler.options = new WebpackOptionsApply().process(options, compiler);

接下来,我们看Compiler模块

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101090.html

相关文章

  • 浅析webpack源码processOptions处理Options以及入口函数(三)

    摘要:我们打开根据上次所返回的这个因为有了上次的基础,比较容易读了大体逻辑是这样的先定义一个空对象同上次的一个逻辑,还是一个目前的方式只有一个满足如果满足的会执行一系列函数这个函数直接结果是的影响是打比如如果满足的话当你的时候就会在页面上出 我们打开bin/cli.js根据上次所返回的Options processOptions(options)这个因为有了上次的基础,比较容易读了,大体逻辑...

    doodlewind 评论0 收藏0
  • 浅析webpack源码前言(一)

    为什么读webpack源码 因为前端框架离不开webpack,天天都在用的东西啊,怎能不研究 读源码能学到很多做项目看书学不到的东西,比如说架构,构造函数,es6很边缘的用法,甚至给函数命名也会潜移默化的影响等 想写源码,不看源码怎么行,虽然现在还不知道写什么,就算不写什么,看看别人写的总可以吧 知道世界的广阔,那么多插件,那么多软件开发师,他们在做什么,同样是写js的,怎么他们能这么伟大 好奇...

    suosuopuo 评论0 收藏0
  • webpack4.x 模块化浅析-CommonJS

    摘要:先看下官方文档中对模块的描述在模块化编程中,开发者将程序分解成离散功能块,并称之为模块。每个模块具有比完整程序更小的接触面,使得校验调试测试轻而易举。 先看下webpack官方文档中对模块的描述: 在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块。每个模块具有比完整程序更小的接触面,使得校验、调试、测试轻而易...

    alphahans 评论0 收藏0
  • 浅析webpack源码Compiler.js模块(八)

    摘要:小尾巴最终返回了属性挂载把引入的函数模块全部暴露出来下面暴露了一些插件再通俗一点的解释比如当你你能调用文件下的方法这个和上面的不同在于上面的是挂在函数对象上的正题要想理解必须要理解再写一遍地址我们先简单的理解它为一个通过注册插件是插件的事 webpack.js小尾巴 const webpack = (options, callback) => { //... if (...

    PumpkinDylan 评论0 收藏0
  • webpack 源码分析()——complier模块

    摘要:源码分析四模块上一篇我们看到,通过对命令行传入的参数和配置文件里的配置项做了转换包装,然后传递给的模块去编译。这一篇我们来看看做了些什么事。在上面的分析中,我们看到最核心的其实就是实例,接下来我们就看下它的类的内部逻辑。 webpack 源码分析(四)——complier模块 上一篇我们看到,webpack-cli 通过 `yargs 对命令行传入的参数和配置文件里的配置项做了转换包装...

    tianlai 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<