幽灵依赖与常见依赖管理

文章目录

  • 前言
      • 1. 演示:检测和修复幽灵依赖
        • 步骤1:安装 depcheck
        • 步骤2:在项目根目录运行 depcheck
        • 可能的输出
        • 步骤3:修复幽灵依赖
      • 2. 依赖管理的好习惯
    • 1. 场景设定
      • 现在有如下依赖需求:
    • 2. 依赖冲突的表现
    • 3. 解决依赖冲突的方法
      • 方法一:统一依赖版本
      • 方法二:强制安装多版本(不推荐,除非特殊需求)
    • 4. 实际操作演示
        • 统一依赖版本
    • 5. 检查依赖冲突
    • 总结


前言

实际项目中发现和修复幽灵依赖问题,并给出常见依赖管理的好习惯。


1. 演示:检测和修复幽灵依赖

假设你的 package.json 如下(只声明了 lodash):

{"name": "root","private": true,"workspaces": ["packages/*"],"devDependencies": {"lerna": "^7.1.5"},"volta": {"node": "18.17.1"}
}

假设你在某个包的代码里写了如下内容:

const _ = require('lodash');
const moment = require('moment'); // 实际未声明依赖

步骤1:安装 depcheck
npm install -g depcheck

步骤2:在项目根目录运行 depcheck
depcheck

可能的输出
Missing dependencies
* moment

这说明你的代码用到了 moment,但 package.json 没有声明。


步骤3:修复幽灵依赖

执行:

npm install moment --save

这样 moment 就会被正确声明到 dependencies 里,幽灵依赖问题解决。


2. 依赖管理的好习惯

  • 用到什么依赖就声明什么依赖,不要依赖于“间接依赖”。
  • 定期用 depcheck 或类似工具检查项目依赖的准确性。
  • 删除未使用的依赖,保持 package.json 干净。
  • 对于 Monorepo 项目,每个包都要单独管理自己的依赖。

下面通过一个实际例子,演示在 Monorepo(如你当前的 Lerna + Yarn/NPM Workspaces 项目)下,子包的依赖管理和依赖冲突的解决方法。


1. 场景设定

假设你的 Monorepo 结构如下:

packages/header/package.jsonfooter/package.jsonremixapp/package.json

现在有如下依赖需求:

  • header 依赖 react@17.0.2
  • footer 依赖 react@18.1.0
  • remixapp 依赖 react@18.1.0

2. 依赖冲突的表现

如果你分别在 headerfooterpackage.json 里声明不同版本的 react,再在根目录执行 yarn installnpm install,包管理器会尝试“扁平化”依赖,但如果版本冲突无法合并,会出现如下情况:

  • node_modules/react 只会有一个版本(比如 18.1.0),
  • header 代码如果用到了 17.x 的特性,可能会报错或行为异常。

3. 解决依赖冲突的方法

方法一:统一依赖版本

最佳实践是在 Monorepo 根目录的 package.json 里统一声明所有子包的公共依赖(如 react),并保证版本一致:

{// ... 其他配置 ..."devDependencies": {"lerna": "^7.1.5","react": "18.1.0","react-dom": "18.1.0"}
}

然后在各子包的 package.json去掉react 的声明,或者用 peerDependencies 指定兼容范围:

{// ... 其他配置 ..."peerDependencies": {"react": ">=18.0.0","react-dom": ">=18.0.0"}
}

这样,所有包都用同一份 react,避免冲突。


方法二:强制安装多版本(不推荐,除非特殊需求)

如果确实有包必须依赖不同版本,可以在子包的 node_modules 里安装特定版本(但会导致包体积变大,依赖树复杂,维护困难)。


4. 实际操作演示

统一依赖版本
  1. 在根目录添加依赖:
npm install react@18.1.0 react-dom@18.1.0 --save-dev
  1. 在子包 footer/package.json 里改为 peerDependencies:
// ... 省略 ..."peerDependencies": {"react": ">=18.0.0","react-dom": ">=18.0.0"},
// ... 省略 ...
  1. 删除子包 dependencies 里的 react/ react-dom,保存后重新安装依赖:
npm install

5. 检查依赖冲突

可以用如下命令检查依赖树:

npm ls react

在这里插入图片描述

如果所有包都指向同一个版本,说明依赖冲突已解决。


总结

  • Monorepo 下建议在根目录统一管理公共依赖,子包用 peerDependencies 声明兼容范围。
  • 避免各子包声明不同版本的同一依赖,否则会出现冲突和幽灵依赖等问题。
  • 定期用 npm lsyarn why 检查依赖树,确保依赖一致性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/76498.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用人工智能大模型,免费快速写工作总结?

如何使用人工智能大模型,免费快速写工作总结? 详细学习视频https://edu.csdn.net/learn/40406/666581

[Java实战经验]异常处理最佳实践

一些好的异常处理实践。 目录 异常设计自定义异常为异常设计错误代码(状态码)设计粒度全局异常处理异常日志信息保留 异常处理时机资源管理try-with-resources异常中的事务 异常设计 自定义异常 自定义异常设计,如业务异常定义BusinessExce…

Makefile 入门指南

Makefile 入门指南 最简单的例子 单文件编译 假设我们有一个main.cpp文件,最简单的Makefile如下: # 最简单的单文件编译 # 目标:依赖文件 main: main.cpp# 编译命令g main.cpp -o main使用步骤: 将上述内容保存为名为Makefile的文件&…

PyTorch数据操作基础教程:从张量创建到高级运算

本文通过示例代码全面讲解PyTorch中张量的基本操作,包含创建、运算、广播机制、索引切片等核心功能,并提供完整的代码和输出结果。 1. 张量创建与基本属性 import torch# 创建连续数值张量 x torch.arange(12, dtypetorch.float32) print("原始张…

【Redis】Redis中的常见数据类型(一)

文章目录 前言一、Redis前置知识1. 全局命令2、数据结构和内部编码3. 单线程架构 二、String 字符串1. 常见命令2. 计数命令3.其他命令4. 内部编码5. 典型使用场景 三、Hash哈希1. 命令2.内部编码3. 使用场景4. 缓存方式对比 结语 前言 Redis 提供了 5 种数据结构,…

Windows 中使用 `netstat` 命令查看端口占用

在 Windows 系统中,可以通过 netstat 命令来查看当前系统的网络连接以及端口的占用情况。以下是关于该命令的具体说明: #### 使用方法 1. **查看所有端口及其状态** 可以通过以下命令查看系统中的所有活动连接和监听端口: bash net…

23种设计模式-结构型模式之装饰器模式(Java版本)

Java 装饰器模式(Decorator Pattern)详解 🎁 什么是装饰器模式? 装饰器模式是一种结构型设计模式,允许向一个对象动态添加新的功能,而不改变其结构。 🧱 你可以想象成在原有功能上“包裹”一…

解决模拟器打开小红书设备异常问题

解决模拟器打开小红书设备异常问题 解决模拟器打开小红书设备异常问题和无法打开问题 解决模拟器打开小红书设备异常问题和无法打开问题 问题描述 最近有用户反馈在模拟器上无法正常登录和打开小红书APP,系统提示"设备异常"错误。本文将详细介绍如何通过…

论文阅读:2025 arxiv AI Alignment: A Comprehensive Survey

总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 AI Alignment: A Comprehensive Survey 人工智能对齐:全面调查 https://arxiv.org/pdf/2310.19852 https://alignmentsurvey.com/ https://www.doubao.com/cha…

精益数据分析(1/126):从《精益数据分析》探寻数据驱动增长之道

精益数据分析(1/126):从《精益数据分析》探寻数据驱动增长之道 在当今数字化时代,数据无疑是企业发展的关键驱动力,对于竞争激烈的程序化广告行业更是如此。最近我在研读《精益数据分析》这本书,收获颇丰&…

第五节:React Hooks进阶篇-如何用useMemo/useCallback优化性能

反模式:滥用导致的内存开销React 19编译器自动Memoization原理 React Hooks 性能优化进阶:从手动到自动 Memoization (基于 React 18 及以下版本,结合 React 19 新特性分析) 一、useMemo/useCallback 的正确使用场景…

windows server C# IIS部署

1、添加IIS功能 windows server 2012、windows server 2016、windows server 2019 说明:自带的是.net 4.5 不需要安装.net 3.5 尽量使用 windows server 2019、2016高版本,低版本会出现需要打补丁的问题 2、打开IIS 3、打开iis应用池 .net 4.5 4、添…

Elasticsearch的Java客户端库QueryBuilders查询方法大全

matchAllQuery 使用方法:创建一个查询,匹配所有文档。 示例:QueryBuilders.matchAllQuery() 注意事项:这种查询不加任何条件,会返回索引中的所有文档,可能会影响性能,特别是文档数量很多时。 ma…

C#进阶学习(六)单向链表和双向链表,循环链表(下)循环链表

目录 📊 链表三剑客:特性全景对比表 一、循环链表节点类 二、循环链表的整体设计框架 三、循环列表中的重要方法: (1)头插法,在头结点前面插入新的节点 (2)尾插法实现插入元素…

交换网络基础

学习目标 掌握交换机的基本工作原理 掌握交换机的基本配置 交换机的基本工作原理 交换机是局域网(LAN)中实现数据高效转发的核心设备,工作在 数据链路层(OSI 模型第二层),其基本工作原理可概括为 “学习…

科学研究:怎么做

科研(科学研究)​​ 是指通过系统化的方法,探索自然、社会或人文领域的未知问题,以发现新知识、验证理论或解决实际问题的活动。它的核心是​​基于证据的探索与创新​​,旨在推动人类认知和技术的进步。 科研的核心要…

算法题(128):费解的开关

审题: 本题需要我们将多组测试用例中拉灯数小于等于6的最小拉灯数输出,若拉灯数最小值仍大于6,则输出-1 思路: 方法一:二进制枚举 首先我们先分析一下基本特性: 1.所有的灯不可能重复拉:若拉的数…

MFC文件-屏幕录像

下载本文件 本文件将获取屏幕图像数据的所有代码整合到两个文件中(ScreenRecorder.h和ScreenRecorder.cpp),使获取屏幕图像数据变得简单。输出IYUV视频流。还可以获取系统播放的声音,输出PCM音频流。由于使用了MFC类,本…

0801ajax_mock-网络ajax请求1-react-仿低代码平台项目

0 vite配置proxy代理 vite.config.ts代码如下图所示: import { defineConfig } from "vite"; import react from "vitejs/plugin-react";// https://vite.dev/config/ export default defineConfig({plugins: [react()],server: {proxy: {&qu…

JVM笔记【一】java和Tomcat类加载机制

JVM笔记一java和Tomcat类加载机制 java和Tomcat类加载机制 Java类加载 * loadClass加载步骤类加载机制类加载器初始化过程双亲委派机制全盘负责委托机制类关系图自定义类加载器打破双亲委派机制 Tomcat类加载器 * 为了解决以上问题,tomcat是如何实现类加载机制的…