本文主要是介绍CJS的module.exports 、 exports和ESM export default和 export详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
webpackg公共源码
function __webpack_require__(moduleId) {if (__webpack_module_cache__[moduleId]) {return __webpack_module_cache__[moduleId].exports;}var module = __webpack_module_cache__[moduleId] = { exports: {} };__webpack_modules__[moduleId](module, module.exports, __webpack_require__);return module.exports;}
结合源码分析以下问题:
-
commonjs同时有 module.exports 、 exports 的情况 输出的一直都是 module.exports 导出的内容 ,exports 不生效
分析:这里简化一下代码,可以结合require方法导入的函数,可以看到module.exports赋值后
module.exports指向了新的变量,这里和第二个参数已经不是同一个对象了,后面exports.xx只是对临时变量进行赋值,并没有什么意义
解决办法:
1.统一用exports
2.用module.exports,需要格外添加module.exports.xxx=valuevar __webpack_modules__ ={"./src/util/math.ts":(module, exports)=>{module.exports ={sum,sub}exports.sumM = sum;exports.subM = sub,} }
-
- 1.esModule(后面简称ESM)模块用commonJS(简称CJS)的reqiure导入后会多包了一层default
- 2.ESM export default导出从另一个模块导入后不能直接解构赋值,
// esModule导出,主要代码 export const formattedDate2 = (date: Date) => {return date; };export default {formattedDate,formattedDate2, } //index.jsimport esModule, { formattedDate2 } from "./util/format"; // const { formattedDate } = esModule; console.log("esModule", esModule, formattedDate2);
同样的简化源码
var __webpack_modules__ ={"./src/util/format.ts":(__unused_webpack_module, __webpack_exports__, __webpack_require__)=>{__webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__),formattedDate2,})const __WEBPACK_DEFAULT_EXPORT__ = ({formattedDate: formattedDate,formattedDate2: formattedDate2})} }var _util_format__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(./src/util/format.ts");console.log("esModule", _util_format__WEBPACK_IMPORTED_MODULE_0__["default"], _util_format__WEBPACK_IMPORTED_MODULE_0__.formattedDate2)
这里注意直接导入的是获取
_util_format__WEBPACK_IMPORTED_MODULE_0__["default"]
,而解构赋值是直接调用的_util_format__WEBPACK_IMPORTED_MODULE_0__
这就是两者 export default 和 export的区别//ESM 特有__webpack_require__.d = function (exports, definition) {for (var key in definition) {if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });}}};// hasOwnProperty() 方法返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性__webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
再看
__webpack_require__.d
函数对Module执行了什么操作,通过Object.defineProperty给exports分别声明default
和formattedDate2
属性 的getter方法和声明该属性可枚举。注意这里没有导出setter方法,所以是不能直接修改导出的变量的,但是我们可以在模块导出setter方法去修改变量(我个人觉得有点像私有变量)。
// esModule增加如下导出, let value = "old"; const setName = (newValue: string) => {value = newValue; };export { value, setName }; //编译的源码如下 __webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__),formattedDate2: () => formattedDate2,setName: () => setName,value: () => value }
这里回过头看问题就清晰了,问题一require导出ESM模块的默认导出一致(看的webpack教程说以前不一样,可能是webpack5修改的),问题2同上,默认导出的是default属性不能直接解构赋值的
这篇关于CJS的module.exports 、 exports和ESM export default和 export详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!