实操理解node_modules目录结构

2023-11-08

环境(2022-8-16):

`node -v`
> v16.15.1

`npm -v`
> 8.11.0

`yarn -v`
> 1.22.19

`pnpm -v`
> 7.9.0

npm0:

mkdir npm0
cd npm0
npm install element-plus --save

此时的目录结构:

+-- node_modules
|   +-- ...
|   +-- dayjs@1.10.4
|   +-- element-plus
|   +-- vue
|   +-- ...
+-- package.json

解析: 这是因为在npm3之后采用了扁平结构,vue是element-plus的依赖,会提升到顶层,形成这样的目录结构,node_modules下其他的依赖也是如此。

此时在目录下再添加index.html文件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">{{ message }}</div>
</body>
<script src="bundle.js"></script>
</html>

添加index.js文件 ,代码如下:

const vue = require('vue')

const { createApp } = vue

createApp({
  data () {
    return {
      message: 'Hello Vue!'
    }
  }
}).mount('#app')

添加 browserify依赖

npm install browserify -D

在package.json中添加打包脚本

"build": "browserify index.js > bundle.js"

 运行打包脚本:

npm run build

然后打开html.index,可正常显示。

 为什么项目依赖中里没有添加vue,但是却可以却是可以使用呢?这是因为node_modules的扁平结构,element-plus依赖了vue,所以可以项目中使用,这也就是所谓的幽灵依赖。


npm1:

mkdir npm1
cd npm1
npm install dayjs@1.11.2 --save

此时的目录结构:

+-- node_modules
|   +-- dayjs@1.11.2
+-- package.json

此时的package.json :

{
  "dependencies": {
    "dayjs": "^1.11.2"
  }
}

然后安装element-plus 

npm install element-plus --save

 安装完成后,新的目录结构

+-- node_modules
|   +-- ...
|   +-- dayjs@1.11.5
|   +-- element-plus@2.2.13
|   +-- ...
+-- package.json

解析: 可以在element-plus的package.json中看到,element-plus也依赖了dayjs

"dayjs": "^1.11.3"

element-plus声明依赖dayjs的最低版本为1.11.3,项目中声明dayjs的最低版本为1.11.2,所以提升到当前的最新版本1.11.5


npm2:

mkdir npm2
cd npm2
npm install element-plus --save

此时的目录结构

+-- node_modules
|   +-- ...
|   +-- element-plus
|   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

此时的package.json : 

{
  "dependencies": {
    "element-plus": "^2.2.13"
  }
}

然后安装dayjs 

npm install dayjs@1.11.2 --save

安装完成后新的目录结构:

+-- node_modules
|   +-- ...
|   +-- dayjs@1.11.2
|   +-- element-plus
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

新的package.json:

{
  "dependencies": {
    "dayjs": "^1.11.2",
    "element-plus": "^2.2.13"
  }
}

 解析:就算当前项目中已通过间接依赖存在了dayjs,若再安装指定版本,还是会优先安装指定的版本。

若指定版本不满足其他包的版本要求,则会在对应包下再安装一份满足条件的版本;

若指定版本满足其他包的版本要求,则会统一使用新的依赖版本(下面是一个具体举例说明);

//  若当时dayjs时指定版本为1.11.4

// npm install dayjs@1.11.4 --save

// 则生成的目录结构如下:

+-- node_modules
|   +-- ...
|   +-- dayjs@1.11.4
|   +-- element-plus
|   +-- ...
+-- package.json

 npm3:

mkdir npm2

cd npm2

npm install element-plus --save
npm install ant-design-vue --save

此时的目录结构:

+-- node_modules
|   +-- ...
|   +-- ant-design-vue
|   +-- element-plus
|   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

然后安装dayjs

+-- node_modules
|   +-- ...
|   +-- dayjs@1.10.4
|   +-- ant-design-vue
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- element-plus
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- ...
+-- package.json 

可以看到 ant-design-vue和element-plus没有共享dayjs这个依赖


 npm4:

模拟从代码仓库clone代码:拷贝npm3下的package.json过来, 然后安装依赖

npm install

此时npm4的目录结构:

+-- node_modules
|   +-- ...
|   +-- dayjs@1.11.5
|   +-- ant-design-vue
|   +-- element-plus
|   +-- ...
+-- package.json

但是npm3的目录结构却不一样: 

+-- node_modules
|   +-- ...
|   +-- dayjs@1.10.4
|   +-- ant-design-vue
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- element-plus
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

 同样的代码,同样的脚本,但是生成的依赖不同,这是因为没有锁定版本。


npm5:

和npm4做相同的事情,但是拷贝时,需要把package-lock.json一起拷贝过来

npm install

此时npm5的目录结构:

+-- node_modules
|   +-- ...
|   +-- dayjs@1.10.4
|   +-- ant-design-vue
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- element-plus
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

可以看到和npm3的结构是完全一样的:

+-- node_modules
|   +-- ...
|   +-- dayjs@1.10.4
|   +-- ant-design-vue
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- element-plus
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

上传package-lock.json这类lockFile是很有必要的,比如前段时间发布的vue2的最后一个版本vue2.7(代号Naruto)支持了Composition Api 这就是同一个大版本中的重大更新,lockFile可以有效避免团队间因本地代码依赖不同产生的问题。


npm6: 

mkdir npm6
cd npm6

npm install element-plus --save
npm install ant-design-vue --save
npm install dayjs@1.10.4 --save
+-- node_modules
|   +-- ...
|   +-- dayjs@1.10.4
|   +-- ant-design-vue
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- element-plus
|   |   +-- node_modules
|   |   |   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

然后执行命令

npm dedupe

 可以看到输出:

removed 2 packages, changed 1 package, and audited 64 packages in 2s

然后依赖的目录结构也发生了变化:

+-- node_modules
|   +-- ...
|   +-- ant-design-vue
|   +-- element-plus
|   +-- dayjs@1.11.5
|   +-- ...
+-- package.json

下面是官方对这个命令的解释

Searches the local package tree and attempts to simplify the overall structure by moving dependencies further up the tree, where they can be more effectively shared by multiple dependent packages

npm7: 

此时先断网,然后拷贝npm3下的package.json过来安装依赖

npm install

输出:

added 63 packages in 45s

 npm采用了离线缓存,下面这个命令可以看到缓存列表

npm cache ls

pnpm3:

拷贝npm3下的package.json过来, 然后安装依赖

pnpm install

会看到报错:

 Unmet peer dependencies
 Peer dependencies that should be installed:
 vue@">=3.2.0 <4.0.0"

此时需要添加vue依赖:

pnpm add vue --save
然后再install后成功,安装成功后的目录结构:
+-- node_modules
|   +-- .pnpm
|   |   +-- ...
|   |   +-- ant-design-vue@3.2.11
|   |   |   +-- node_modules
|   |   |   |   +-- ...
|   |   |   |   +-- dayjs@1.11.5
|   |   |   |   +-- ...
|   |   +-- dayjs@1.11.5
|   |   +-- element-plus@2.2.13
|   |   |   +-- node_modules
|   |   |   |   +-- ...
|   |   |   |   +-- dayjs@1.11.5
|   |   |   |   +-- ...
|   +-- ant-design-vue
|   +-- dayjs
|   +-- element-plus
|   +-- vue
+-- package.json
+-- pnpm-lock.yaml

在文件资源管理器里可以看到ant-design-vue, dayjs 这些重复依赖都是以符号链接的形式存在,而且依赖结构也没有扁平化。 


npm yarn pnpm 发展历程

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实操理解node_modules目录结构 的相关文章

随机推荐

  • C语言向上取整数简单写法

    C语言整数除法向上取整 define GET M N M 1 N 1 实例 一共100字节的数据 一次发送11字节 需要发送多少次 GET 100 16 7 次
  • 记录一道leetcode算法题的坑

    题目链接 这个题并不难 只是想让自己牢记一句老话 题目里面的每个条件都有用 int twoSum int nums int numsSize int target int returnSize int a 2 0 注意 注意 注意 retu
  • Mathematica 随机打乱列表顺序/列表随机重排列

    更新 找到相关函数了 没仔细看说明以为RandomSample只能随机取样来着 汗 RandomSample list 原内容 没必要看了 没有找到直接的相关函数 想到的方法是随机交换列表元素 例如以下程序为1 10的数字乱序 Permut
  • IP数据包长度问题总结

    首先要看TCP IP协议 涉及到四层 链路层 网络层 传输层 应用层 其中以太网 Ethernet 的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据 Data 在应用层 它们的关系是 数据帧 IP包 TCP
  • TypeError: write() argument must be str, not bytes报错原因及Python3写入二进制文件方法

    Python2随机写入二进制文件 with open python2 random bin w as f f write os urandom 10 但使用Python3会报错 TypeError must be str not bytes
  • Java设计模式:深入解析与应用示例

    文章目录 引言 一 单例模式 二 工厂模式 三 抽象工厂模式 四 建造者模式 五 原型模式 六 适配器模式 七 装饰器模式 八 观察者模式 九 策略模式 十 命令模式 结语 引言 设计模式是一种在特定上下文中反复出现的可重用解决方案 用于处
  • Linux / ldd 命令的介绍与使用

    0 介绍 ldd 用来打印或者查看程序运行所需的共享库 访问共享对象依赖关系 常用来解决程序因缺少某个库文件而不能运行的一些问题 1 首先 ldd 不是一个可执行程序 而只是一个 shell 脚本 2 ldd 能够显示可执行模块的 depe
  • 学习笔记Flink(八)—— 基于Flink 在线交易反欺诈检测

    一 背景介绍 信用卡欺诈 信用卡欺诈是指故意使用伪造 作废的信用卡 冒用他人的信用卡骗取财物 或用本人信用卡进行恶意透支的行为 在当今数字时代 信用卡欺诈行为越来越被重视 罪犯可以通过诈骗或者入侵安全级别较低系统来盗窃信用卡卡号 用盗得的信
  • mipi和isp处理_ISP-摄像头的最强大脑- 图像质量及色彩科技知识分享平台 图像质量与色彩管理 - Powered by HDWiki!...

    做为拍照手机的核心模块之一 camera sensor效果的调整 涉及到众多的参数 如果对基本的光学原理及sensor软 硬件对图像处理的原理能有深入的理解和把握的话 对我们的工作将会起 到事半功倍的效果 否则 缺乏了理论的指导 只能是凭感
  • 【系统篇 / 文件】01. 文件服务安装与配置 ❀ Windows Server 2008 R2

    简介 文件服务提供帮助管理存储 启用文件复制 管理共享文件夹 确保快速搜索文件 以及启用对UNXI客户端计算机访问的技术 使用文件服务 组织可以将文件存储到中心位置 然后通过公司网络与用户共享 可以为这些共享文件创建索引 以帮助用户快速查找
  • K8S deployment可视化故障排查指南

    这是一个示意图 可帮助您调试Kubernetes中的deployemnt 当您希望在Kubernetes中部署应用程序时 通常定义三个组件 一个deployment 这是创建名为Pods的应用程序副本的秘诀 一个service 内部负载平衡
  • cocos creator 中读取Excel表格中的数据

    一 使用相应工具将Excel文件转化成JSON文件导入到cocos creator资源文件 二 在VS中对Excel文本中的数据进行转换 Excel文本中各项数据的名称对应代码中的data export default class Task
  • Apache-tomcat-8.5.82下载安装以及环境变量配置

    一 下载apache tomcat 8 5 82 1 进入apache官网 Apache Tomcat Welcome 选择Download gt Tomcat8 进入Apache Tomcat Apache Tomcat 8 Softwa
  • 分布式计算,泛在计算,BOINC

    BOINC平台简介 知乎 Download BOINC client software 开源源代码 https github com BOINC boinc 介绍 https www equn com wiki BOINC 使用指南 htt
  • 【Antdv】a-date-picker showTime带时间默认00:00:00

    show time 默认当前系统时间 设置默认 00 00 00
  • 预编码

    原则上说MIMO技术并不一定需要预编码 使用预编码的前提是发射端可以及时获取信道信息 也就是CSIT 在通常情况下 只有接收端可以知道信道信息CSIR 在这个情况下 接收端通过复杂的信号处理算法 如MMSE SIC 可以解调出多路的MIMO
  • Zookeeper 通知更新可靠吗? 解读源码找答案!

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由特鲁门发表于云 社区专栏 导读 遇到Keepper通知更新无法收到的问题 思考节点变更通知的可靠性 通过阅读源码解析了解到zk Watch的注册以及触发的机制 本地调试运行模拟
  • 软件架构及几种典型框架

    什么是软件架构 什么是软件框架 很多时候 我们常常会混用架构和框架这两个词 实际上 广义上的架构和框架在概念上有很大的不同 架构给人的感觉 包容上更大 所以实际上架构是包含了框架的概念的 广义的架构应为一个系统的架构 不仅仅涉及软件中的技巧
  • BOM编程

    1 BOM概述 BOM 浏览器对象模型 Browser Object Model 它提供了独立于内容的 可以与浏览器窗口进行互动的对象结构 通过BOM可以操作浏览器窗口 比如弹出框 控制浏览器跳转 获取分辨率等 BOM是把 浏览器 当做一个
  • 实操理解node_modules目录结构

    环境 2022 8 16 node v gt v16 15 1 npm v gt 8 11 0 yarn v gt 1 22 19 pnpm v gt 7 9 0 npm0 mkdir npm0 cd npm0 npm install el