• 如何检测JavaScript 项目中循环依赖关系?
  • 发布于 2个月前
  • 143 热度
    0 评论
在软件工程中,循环依赖是指两个或多个模块之间的关系,这些模块直接或间接地相互依赖才能正常运行。循环依赖可能会导致不同程度的问题。JavaScript 中的循环依赖关系就像鸡和蛋的关系,下面通过一个商品和购物车的示例来具体分析:
// 堆代码 duidaima.com
// Product.js
const Cart = require('./Cart');

function Product(name, price) {
  this.name = name;
  this.price = price;
}

Product.prototype.addToCart = function() {
  Cart.addProduct(this); // Adding this product to the Cart
}

module.exports = Product;

// Cart.js
const Product = require('./Product');

let productsInCart = [];

const Cart = {
  addProduct: function(product) {
    productsInCart.push(product);
    console.log(`${product.name} added to cart`);
  },
  displayCart: function() {
    return productsInCart.map(p => `${p.name}: $${p.price}`).join(', ');
  }
}

module.exports = Cart;
Product 和 Cart 相互依赖的情况被称为循环依赖,它会给你的代码带来一些复杂的问题:
可维护性:当模块紧密相连时,更改一个部分往往需要更改其他部分,从而导致出现错误的几率增加。
测试:由于每个模块都不是孤立的,测试变得更具挑战性。您可能需要加载多个模块才能测试一个功能。
紧密耦合:模块之间相互依赖程度高,降低了灵活性。
初始化问题:由于存在循环依赖关系,一个模块可能会尝试使用另一个尚未完全加载的模块。这可能会导致错误或初始化不完整,从而导致应用程序出现不可预测的行为或崩溃。
对性能的影响:循环依赖关系会导致内存泄漏或执行路径效率低下,从而降低应用程序的性能。

可扩展性问题:随着应用程序的增长,循环依赖关系会增加扩展代码库的难度。当代码库充满复杂的相互依赖关系时,添加新功能或扩展现有功能就会变得更加困难。


如何防止循环依赖呢?
本文将介绍 3 种常用的循环依赖检测工具和方法:GitHub Actions、ESLint 和 Bit。
1.Github Actions
GitHub Actions 是一个 CI/CD 平台,可让您直接从 GitHub 仓库自动化构建、测试和部署管道。它允许你创建工作流,在推送或拉取请求等特定触发时自动执行。通过将工具或脚本集成到工作流中,您可以使用 GitHub Actions 检测循环依赖关系。例如:
Madge:命令行工具,用于生成模块依赖关系的可视化图表,可用于检测循环依赖关系。
dependency-cruiser:验证和可视化依赖关系的 NPM 软件包。
eslint-plugin-import:主要用于对导入进行过滤,某些 ESLint 配置和插件(eslint-plugin-import)可帮助检测循环依赖关系。-Custom Scripts:根据项目的复杂程度,您也可以编写自定义脚本来检查循环依赖关系。
下面是一个使用 Madge 检测循环依赖关系的 GitHub Actions 工作流程的基本示例:
name: Circular Dependency Check
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Node.js
      uses: actions/setup-node@v1
      with:
        node-version: '18'
    - name: Install dependencies
      run: npm install
    - name: Check for circular dependencies
      run: npx madge --circular ./path/to/your/code

在此工作流程中,每个推送和拉取请求都会触发动作。如果检测到循环依赖关系,动作会导致构建失败并向开发人员发送通知。开发人员的典型反应应该是检查报告的依赖关系,重构代码以打破循环,并将更改推回版本库。

2.ESLint
ESLint 是 JavaScript 社区广泛使用的静态代码分析工具。ESLint 通常用于执行编码标准和识别语法错误或反模式,还可以检测 JavaScript 项目中的循环依赖关系。要使用 ESLint 检测循环依赖关系,需要对其进行适当配置。ESLint 并没有直接检测循环依赖关系的内置规则,但它可以与 eslint-plugin-import 这样的插件结合使用,后者提供了一个 no-cycle 规则来检测导入循环。你可以通过 NPM 轻松安装这个插件:
npm i eslint-plugin-import
安装插件后,您需要配置 ESLint 设置以使用它。这需要在项目的 ESLint 配置文件(.eslintrcor,.eslintrc.js,.eslintrc.json 视设置而定)中完成。在配置文件中,您需要

添加插件:在插件列表中加入 eslint-plugin-import。
配置无循环规则:该规则专门用于检测循环依赖关系。
{
  "extends": ["eslint:recommended"],
  "plugins": ["import"],
  "rules": {
    // other rules...
    "import/no-cycle": [2, { "maxDepth": "∞" }]
  },
  // other configurations...
}

在这里,"no-cycle" 规则中的 maxDepth 选项决定了插件将深入模块导入以检测循环的深度。由于 maxDepth 设置为无穷大("∞"),ESLint 将检查所有深度的导入是否存在循环。

3.Bit
Bit 是用于可组合软件的下一代构建系统。你可以在独立的空间内设计、开发、构建、测试和版本控制一个组件。它在前端开发中尤其流行,但并不仅限于此。以下是 Bit 的一些关键方面:
1.允许团队共享和协作项目中的单个组件,而不是整个代码库。
2.就像 Git 管理源代码版本一样,Bit 也管理单个组件的版本。它能跟踪组件随时间发生的变化,使更新和维护更加容易。
3.Bit 的设计旨在实现组件的隔离开发和测试。每个组件都可以独立于项目的其他部分进行开发、测试和部署。
4.它提供了一种记录组件的方法,使组件更容易理解并在项目中使用。
5.在循环依赖检测方面,Bit 是一种预防方法,而不是检测方法。如果存在循环依赖关系,Bit 会检测并阻止你导出代码。

结论
本文讨论了发现和修复 JavaScript 项目中循环依赖关系的 3 种简单而强大的方法。

GitHub Actions 可以在您将代码推送到 GitHub 时自动捕获这些问题,而 ESLint 则可以在您编写代码时发现并高亮显示任何循环依赖关系。Bit 是一种独特的解决方案,它能在循环依赖关系开始之前就加以预防。这些工具能让你的编码生活更轻松,让你的项目运行更顺畅。
用户评论