当前位置: 首页 > news >正文

各类企业网站案例杭州营销型网站建设工作室

各类企业网站案例,杭州营销型网站建设工作室,广州营销网站制作,网站页面设计内容模块循环依赖问题 在项目比较小的时候可能不怎么会遇到这个问题,但项目一旦有一定的体量后就可能会遇到了。 我之前做项目时就遇到这个问题,也是总结一篇文章。 比如这种类型的报错 commonjs存在的问题 先讲一下commonjs存在的问题。 CommonJS模块采…

模块循环依赖问题

在项目比较小的时候可能不怎么会遇到这个问题,但项目一旦有一定的体量后就可能会遇到了。
我之前做项目时就遇到这个问题,也是总结一篇文章。

比如这种类型的报错
在这里插入图片描述

commonjs存在的问题

先讲一下commonjs存在的问题。
CommonJS模块采用深度优先遍历,并且是加载时执行,即脚本代码在require时就全部执行。一旦出现某个模块被“循环加载”,就只输出已经执行的部分,没有执行的部分不会输出。
举例子

// a.js
require("./b.js");
exports.a = function () {};// b.js
const { a } = require("./a");
a();// index.js
require("./a.js");

执行index.js
结果:报错a is not function
执行流程
1 导入a.js

require("a.js")
// 此时moduleCache
moduleCache = {moduleA : {}
}

2 执行a.js为moduleA添加属性,发现第一行导入b.js,模块a还没执行完,执行b.js

require("./b.js");
// 此时moduleCache
moduleCache = {moduleA : {},moduleB : {}
}

3 执行b.js,发现导入a.js,此时moduleCache有moduleA,不会重复执行模块a的代码,会直接用moduleCache中模块a已经导出的内容。

const { a } = require("./a");
等价于
const {a} = moduleCache.moduleA

因为此时模块a的内容还未完全执行完,所以解构的变量a是undefined,还不是function,所以报错。

webpack打包结果分析

// a.js
import "./b.js";
export const A = () => {};// b.js
import { A } from "./a.js";
A();// index.js
import "./a";

webpack打包结果

(() => {"use strict";var __webpack_modules__ = {"./src/a.js": (__unused_webpack_module,__webpack_exports__,__webpack_require__) => {__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__, {A: () => A,});var _b_js__WEBPACK_IMPORTED_MODULE_0__ =__webpack_require__("./src/b.js");var A = function A() {};},"./src/b.js": (__unused_webpack_module,__webpack_exports__,__webpack_require__) => {__webpack_require__.r(__webpack_exports__);var _a_js__WEBPACK_IMPORTED_MODULE_0__ =__webpack_require__("./src/a.js");(0, _a_js__WEBPACK_IMPORTED_MODULE_0__.A)();},};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) {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);})();(() => {__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__ = {};__webpack_require__.r(__webpack_exports__);var _a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/a.js");
})();

每个模块的代码会被放到一个对象

var __webpack_modules__ = {[moduleId] : 模块代码
}
var __webpack_modules__ = {"./src/a.js": (__unused_webpack_module,__webpack_exports__,__webpack_require__) => {__webpack_require__.r(__webpack_exports__); // 标记模块为ES模块__webpack_require__.d(__webpack_exports__, {A: () => A, // getter});var _b_js__WEBPACK_IMPORTED_MODULE_0__ =__webpack_require__("./src/b.js");var A = function A() {};},"./src/b.js": (__unused_webpack_module,__webpack_exports__,__webpack_require__) => {__webpack_require__.r(__webpack_exports__);var _a_js__WEBPACK_IMPORTED_MODULE_0__ =__webpack_require__("./src/a.js");(0, _a_js__WEBPACK_IMPORTED_MODULE_0__.A)();},};

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: {},});__webpack_modules__[moduleId](module, module.exports, __webpack_require__);return module.exports;
}

跟commonjs规范类似

  1. 查看缓存是否有模块导出结果,如果模块执行过了,返回模块导出结果
  2. 在执行模块代码之前,先创建模块导出对象module.exports
  3. 将模块导出对象传入执行模块代码
__webpack_require__.d // 定义模块导出属性
__webpack_require__.o // 检查模块导出对象是否具有某个属性
__webpack_require__.r // 标记模块为ES模块

模块代码执行前会先进行

  1. 将模块导出对象标记ES模块
  2. 如果模块有导出内容,会将这些内容定义到模块导出对象

代码执行流程
模块A执行

__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {A: () => A, // 定义getter
});
var _b_js__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__("./src/b.js"); // 执行到这里 会暂停a模块代码执行,执行b模块var A = function A() {};

moduleA 定义了一个A属性,A属性是一个存取器属性,有getter,getter就是返回真正导出的A。
执行b模块时,()=>A,这里返回的A还是undefined。
执行b模块

__webpack_require__.r(__webpack_exports__);
var _a_js__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__("./src/a.js");(0, _a_js__WEBPACK_IMPORTED_MODULE_0__.A)();

跟Commonjs的问题一样,模块A还没有执行完,A还没有赋值,所以A这里是undefined,不能作为函数调用。
这里和commonjs还是有些区别
打包结果中模块代码执行前会去先定义导出属性,为属性设置一个getter,因此在代码模块执行前这些导出属性就已经在导出对象中有getter。
这里因为配置babel,打包结果会把const转成var,所以变量声明提升了,如果是const就会变成变量在声明前使用。

结论

项目会形成循环依赖实际开发中很难避免,有可能引入了某个模块就会导致形成依赖链路。

形成循环依赖链路并不一定会报错,但是在执行到对应模块时,之前模块因为导入其他包,模块代码还没完全执行完,内容还没完全导出,就有可能导致报错。
其实导致报错还好,因为可以提前在本地就感知到处理,但是如果你只是定义了一个变量,那么这个变量可能是在你还没有赋值的时候,就引用了,所以其实模块导出的变量并不是一定可信的。

其实在遇到函数调用报错时可以通过把一些函数表达式改成函数声明就好,因为打包结果模块的执行其实是执行一个函数,在执行前会有函数声明提升,但尽量不要用这种规范来处理,因为很可能会遇到更多坑。
其实有模块循环依赖后还报错,本身就是这条依赖链路有问题,应该找到不合理的地方解决,而不是去规避。用函数声明解决一些问题,反倒会留下一些坑,可能某些环境的值原本因为循环依赖导致引用时是undefined,但是碰巧你用函数声明避免了一些报错,导致埋了一个坑。

有一些工具可以分析项目中的循环链路,eslint也有相应的配置。
至于如何找到循环依赖的不合理地方就凭经验吧,这里就不展开了,毕竟是个人观点。

http://www.yayakq.cn/news/685240/

相关文章:

  • 比较好的室内设计网站广州市品牌网站建设服务机构
  • 怎么做视频解析的网站优秀网站设计网站
  • 分类信息系统网站模板企业云邮箱
  • 网站怎么认证你懂的我的意思正能量句子
  • 哪个门户网站做推广好织梦商城网站模板
  • 环球旅行社网站建设规划书品牌宣传文案范文
  • 建设银行网站上不去嵊州建设局网站
  • 天猫网站建设的目标是什么wordpress不升级能用吗
  • wordpress首页标题不显示网站描述自己如何开自己的商城
  • 网站建设风景课程设计报告高端网站官网
  • 怎么搭建一个简单的网站百度推广负责做网站吗
  • 网站策划书包含的内容做网站wordpress
  • 做exo小说的网站在易语言里面做网站
  • 四川建设安全协会网站微信小程序后台管理系统
  • 九江网站开发公司网站建设代理协议
  • 绵阳做网站哪家公司好做网站的启蒙思想
  • 网站信息员队伍建设生产企业erp系统开发
  • 高端网站建设 n磐石网络小程序商城图片
  • 保健品网站建设背景2017织梦网站怎么做seo
  • 建设网站好难公司做网站有什么用
  • 长沙网站定制电子书网站搭建教程
  • 个人网站广告投放高质量的常州网站建设
  • 网站分析数据网站制作价格明细
  • 新加坡服务器网站需要备案么wordpress最新主题
  • 上海手机网站建设多少钱图书馆网站建设的意义
  • 网站建设与 维护实训报告范文嘉兴专业网站建设
  • 表白视频制作网站wordpress下载功能
  • 延吉网站网站建设定制网站模板站
  • 怎么把网站做的更好建设银行手机银行官方网站下载安装
  • 装饰公司营销型网站设计网站开发qq群