我们直接看一下webpack加载器伪代码

var d = {}; // 缓存模块

// 功能模块
var e = {
    0: function(module, exports, require) {
        exports.sayHello = function() {
            console.log("Hello, world!");
        };
    },
    1: function(module, exports, require) {
        var hello = require(0);
        hello.sayHello();  // 执行模块 0 中的 `sayHello` 方法
    }
};

function a(f) { // 加载器
    if (d[f])                  // 如果模块已缓存,返回缓存中的导出对象
        return d[f].exports;

    // 如果模块未被缓存,初始化缓存对象
    var c = d[f] = {
        i: f,                   // 模块的标识符(ID)
        l: !1,                  // 加载状态(false 表示未加载)
        exports: {}             // 初始化导出对象
    };

    // 执行模块的定义函数,设置上下文为exports,并传递 `exports`、`module` 和 `require`
    e[f].call(c.exports, c, c.exports, a);

    // 标记模块为已加载
    c.l = !0;
    
    // 返回模块的导出对象
    return c.exports;
}

a.e = "asdasd"
console.log(a.e,a); 
/*
输出 asdasd [Function: a] { e: 'asdasd' }
a可以简单理解变成了类,a()是构造函数
*/
a(1) // 输出Hello, world!

执行流程

  1. 调用a(1)
  2. 使用到了e内的0方法,使用加载器来获取
  3. 发现d缓存中不存在,创建一个对象,同时给d[f]和c赋值过去
  4. 再次通过e[f].call调用e[0]函数,将上下文的变成{},传递模块和导出以及加载器
  5. 0函数将空{}添加一个sayHello函数
  6. 加载器返回在require(0)运行时创建的c变量的exports
  7. hello变量接收,实际hello变为了 { sayHello: function() }
  8. 调用sayHello变量

结论

因此我们扣模块时候将加载器部分赋值一个变量,就可以操控整个对象包括有关加载器,然后调用缺啥补啥即可

// 功能模块
var e = {
    0: function(module, exports, require) {
        exports.sayHello = function() {
            console.log("Hello, world!");
        };
    },
    1: function(module, exports, require) {
        var hello = require(0);
        hello.sayHello();  // 执行模块 0 中的 `sayHello` 方法
    }
};

let loader = {}
// 真实环境中下面{}内为单独文件,这里用{}分开让他与外部互不影响
{
    function a(f) {
        if (d[f])
            return d[f].exports;
        var c = d[f] = {
            i: f,
            l: !1,
            exports: {}
        };
        e[f].call(c.exports, c, c.exports, a);
        c.l = !0;
        return c.exports;
    }

    loader = a; // 直接把加载器赋值到loader上

    var d = {}; // 缓存模块
    a.e = "asdasd" // a上的方法或值
}

console.log(loader.e); // 输出asdasd
loader(1) //输出Hello, world!
文章目录