webpack esmodule、commonjs生成代码解析

commonjs 模块代码

文件目录

// index.js入口文件
const testName = require('./testName.js')
console.log(testName)

// testName.js文件
module.exports = 'testName: xiaoMing'

生成代码

(() => {
  var __webpack_modules__ = ({
    "./testName.js": ((module) => {
      module.exports = 'testName: xiaoMing';
    })
  });
  // 缓存模块加载结果
  var __webpack_module_cache__ = {};
  
  // 通过__webpack_require__进行模块的加载
  function __webpack_require__(moduleId) {
    var cachedModule = __webpack_module_cache__[moduleId];
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }
    var module = __webpack_module_cache__[moduleId] = {
      exports: {}
    };
    // 在这里moduleId即为:"./testName.js",加载__webpack_modules__对象中对应的方法
    __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    return module.exports;
  }
  (() => {
    // 如果加载的模块又加载了其他模块,会通过__webpack_require__递归解析
    var testName = __webpack_require__("./testName.js");
    console.log(testName);
  })();
})()

esmodule 模块代码

文件目录

// index.js文件,删除原有代码,用下边代码覆盖
import testName, { age } from './testName.js'
console.log(testName, age)

// testName.js
export default 'test_name_xiaoMing'
export const age = 'test_age_22'

生成代码

(() => {
  "use strict";
  var __webpack_modules__ = {
    "./testName.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
      // 标识是esmoudle模块
      __webpack_require__.r(__webpack_exports__);
      // 通过Object.defineProperty定义导出对象的内容
      __webpack_require__.d(__webpack_exports__, {
        "age": () => age,
        "default": () => __WEBPACK_DEFAULT_EXPORT__
      });
      const __WEBPACK_DEFAULT_EXPORT__ = 'test_name_xiaoMing';
      var age = 'test_age_22';
    }
  };
  var __webpack_module_cache__ = {};
  // 加载模块的方法
  function __webpack_require__(moduleId) {
    var cachedModule = __webpack_module_cache__[moduleId];
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }
    var module = __webpack_module_cache__[moduleId] = {
      exports: {}
    };
    __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    return module.exports;
  }
  
  (() => {
    __webpack_require__.d = (exports, definition) => {
      for (var key in definition) {
        // 如果给出的对象中有,但要导出的对象中没有,才通过Object.defineProperty在导出对象中定义
        if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
          Object.defineProperty(exports, key, {
            enumerable: true,
            get: definition[key]
          });
        }
      }
    };
  })();
  
  (() => {
    // 检测对象是否存在某个属性 
    __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
  })();
  
  (() => {
    // 标识esmodule模块的方法
    __webpack_require__.r = exports => {
      if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
        Object.defineProperty(exports, Symbol.toStringTag, {
          value: 'Module'
        });
      }
      Object.defineProperty(exports, '__esModule', {
        value: true
      });
    };
  })();
  
  var __webpack_exports__ = {};
  (() => {
    // 标识入口文件是否是esmodule
    __webpack_require__.r(__webpack_exports__);
    // 返回导出的内容
    var _testName_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./testName.js");
    console.log(_testName_js__WEBPACK_IMPORTED_MODULE_0__["default"], _testName_js__WEBPACK_IMPORTED_MODULE_0__.age);
  })();
  
})();
  • 和commonjs的区别

  • 可以看到在esmodule生成的代码中,最后确定导出对象的内容是通过 Object.defineProperty 定义的,而commonjs直接添加进对象,这其实和两个模块导出内容的方式有关:
    • esmodule导出的是一个引用,在内部修改后,任何地方都可以获取到它模块内最新的值,但commonjs仅仅是值的拷贝,内部修改了这个值,就不会再同步到外部
    • 二者的区别如下:
// commonjs
let age = 1
let obj = { age: age }
console.log(obj.age) // 1
age = 222
console.log(obj.age) // 1

// esmodule
let age = 1
let obj = {}
Object.defineProperty(obj, 'age', {
    enumerable: true,
    get: () => age
})
console.log(obj.age) // 1
age = 222
console.log(obj.age) // 222

commonjs require esmodule 模块代码

文件目录:

// index.js文件,删除原有代码,用下边代码覆盖
const testName = require('./testName.js')
console.log(testName.default, testName.age)

// testName.js文件
export default 'test_name_xiaoMing'
export const age = 'test_age_22'

生成代码:

(() => {
  var modules = {
    "./testName.js": (module, exports, require) => {
      "use strict";
      require.r(exports);
      // cjs 导入 esm 的内容,遵循esm的值导出规范,通过Object.defineProperty定义导出内容
      require.d(exports, {
        "age": () => age,
        "default": () => _DEFAULT_EXPORT__
      });
      const _DEFAULT_EXPORT__ = 'test_name_xiaoMing';
      var age = 'test_age_22';
    }
  };
  var cache = {};
  function require(moduleId) {
    var cachedModule = cache[moduleId];
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }
    var module = cache[moduleId] = {
      exports: {}
    };
    modules[moduleId](module, module.exports, require);
    return module.exports;
  }
  require.d = (exports, definition) => {
    for (var key in definition) {
      Object.defineProperty(exports, key, {
        enumerable: true,
        get: definition[key]
      });   
    }
  };
  require.r = exports => {
    Object.defineProperty(exports, Symbol.toStringTag, {
      value: 'Module'
    });
    Object.defineProperty(exports, '__esModule', {
      value: true
    });
  };
  (() => {
    var testName = require("./testName.js");
    // esm 默认导出的内容,需要通过['default']获取
    console.log(testName["default"], testName.age);
  })();
})();

esmodule import commonjs 模块代码

文件目录:

// index.js文件
import testName, { age } from './testName.js'
console.log(testName, age)

// testName.js文件
module.exports = {
  age: 'age_11',
  testName: 'test_xiaoMing'
}

生成代码:

(() => {
  var modules = {
    "./testName.js": module => {
      // 导入 cjs 模块内容,遵循 cjs 值导出规范,只是值的拷贝,直接放在对象上
      module.exports = {
        age: 'age_11',
        testName: 'test_xiaoMing'
      };
    }
  };
  var cache = {};
  
  function require(moduleId) {
    var cachedModule = cache[moduleId];
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }
    var module = cache[moduleId] = {
      exports: {}
    };
    modules[moduleId](module, module.exports, require);
    return module.exports;
  }
  
  require.d = (exports, definition) => {
    for (var key in definition) {
      Object.defineProperty(exports, key, {
        enumerable: true,
        get: definition[key]
      });
    }
  };
  
  require.r = exports => {
    Object.defineProperty(exports, Symbol.toStringTag, {
      value: 'Module'
    });
    Object.defineProperty(exports, '__esModule', {
      value: true
    });
  };
  // 会新增一个根据不同模块,获取导出内容的方法,如果是 esm 则 module['default'] ,如果是 cjs 则 直接返回module
  // 模块会通过 require.r 来进行标识
  require.n = module => {
    var getter = module && module.__esModule ? () => module['default'] : () => module;
    // 就是给当前的getter添加了个a属性,指向自己,作用其实就是在获取默认导出对象的时候,不需要加()执
    // 行只需要getter.a便可以获取到默认导出对象
    require.d(getter, {
      a: getter
    });
    return getter;
  };
  var exports = {};
  (() => {
    "use strict";
    // 判断入口文件是否是 esm
    require.r(exports);
    // 获取导出对象
    var _testName_js_0__ = require("./testName.js");
    
    // 这里导入的内容没有通过require.r标识,所以返回的内容直接就是一个() => module
    var _testName_js_0___default = require.n(_testName_js_0__);
    console.log(_testName_js_0___default(), _testName_js_0__.age);
  })();
})();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值