继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

webpack 与循环引用

白胜
关注TA
已关注
手记 5
粉丝 7
获赞 16

循环引用的基本表现是:a 文件引入了 b 文件的模块,b 文件引入了 a 文件的模块。也有多个文件的循环引用,比如 a 引入 b 模块,b 引入 c 模块,c 引入 a 模块。

理论上循环引用会导致栈溢出,但并非所有循环引用都会导致栈溢出,比如下例,执行 webpack 打包出的文件,会依次打印:undefined、b、a
图片描述

什么情况下才会导致栈溢出呢?在导出模块中相互调用对方,才会导致栈溢出。比如下面的例子:
图片描述

看看打包出的代码(去除了部分无关代码):

/******/ (function(modules) {
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
          "use strict";
          var __WEBPACK_IMPORTED_MODULE_0__b__ = __webpack_require__(2);

          __webpack_exports__["a"] = (val => {
             Object(__WEBPACK_IMPORTED_MODULE_0__b__["a" /* default */])('a')
             console.log(val)
          });
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
           "use strict";
           Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
           var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0);
           // 入口文件
           Object(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* default */])(1)
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
           "use strict";
           var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0);

           __webpack_exports__["a"] = (val => {
                Object(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* default */])('b')
                console.log(val)
           });
/***/ })
]);

执行顺序:

  • 执行模块 1,执行 __webpack_require__(0)
  • 执行模块 0,执行 __webpack_require__(2)
  • 执行模块 2,模块 2 完成安装(b.js),导出一个函数
  • 继续执行模块 0,模块 0 完成安装(a.js),导出一个函数
  • 继续执行模块 1,执行 (_WEBPACK_IMPORTED_MODULE_0__a__["a"])(1)__WEBPACK_IMPORTED_MODULE_0__a_ 拿到的是对 __webpack_require__(0) 的引用,即:
{
  a: val => {
    Object(__WEBPACK_IMPORTED_MODULE_0__b__["a" ])('a')
    console.log(val)
  }
}

调用 WEBPACK_IMPORTED_MODULE_0__a__["a"] 又会执行 __WEBPACK_IMPORTED_MODULE_0__b__["a"]_WEBPACK_IMPORTED_MODULE_0__b_ 是对 __webpack_require__(2) 的引用,即:

{
  a: val => {
    Object(__WEBPACK_IMPORTED_MODULE_0__a__["a"])('b')
    console.log(val)
  }
}

相当于:

f1 = () => f2();
f2 = () => f1();
f1();

既然 webpack 不会因为循环引用导致打包出错,也就意味着项目中可能隐藏着未知的循环引用,怎么才能知道是否存在循环引用呢?有一个插件可以解决这个问题:circular-dependency-plugin

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP

热门评论

大神 再掘金也看见你的专栏 什么时候出视频课程 我买

查看全部评论