npm相关机制解析

2023-05-16

你对日常使用的npm了解的有多少?

从这篇文章中能获得什么?

  1. npm的安装机制,即在执行install命令时都做了什么事?
  2. npm的缓存策略,这里做了简单介绍,没深入。
  3. npm的依赖管理,即我们每次安装的依赖都是怎么在node_modules进行管理的?
  4. lock文件究竟有什么用?我们到底需要吗?

如果大家对上面三点都很清楚,那就不用浪费太多时间,简单回顾一下就好。 如果不清楚的话可以沉下心看8分钟。

npm依赖安装机制

首先我们来了解一下npm依赖安装的设计哲学:

npm安装依赖的时候会优先安装在当前项目的目录下,保持各个项目依赖的独立性。

优点: 可以减少开发者的心智负担,方便维护各个项目下的不同依赖。

缺点:A项目和B项目都依赖一个包,这时候就会产生依赖重复安装,造成电脑内存资源的浪费。

当然像webpackcreat-react-app这些依赖也可以安装在全局,这样做的目的是为了方便设置环境变量path,让我们可以在任何地方调用对应的命令

了解了这些以后我们来探究一下npm依赖安装的核心机制。

npm和yarn.png

 通过上图我们可以看到npm安装依赖的整个脉络,接下来我们逐个分析​

当我们执行npm install命令时,会首先去查找对应的配置文件,来告诉npm要以什么样的规则去下载文件。 config文件有多个,但是遵循一个优先级: 项目级的.npmrc > 用户级的.npmrc > 全局的.npmrc > npm内置的.npmrc文件

我们可以通过npm config ls -l来查看当前的配置

确定了config之后,就会看当前项目下有没有package-lock.json文件。​

如果有package-lock.json文件,那么会对比pacakge.jsonlock文件:

  1. 如果依赖版本规范兼容的话,会按照lock文件中的信息进行资源的下载
  2. 如果依赖版本规范不兼容的话,不同版本会有不同的处理(详情看上图)

其实大部分情况下两个版本规范都是兼容的,所以大部分都是按照lock文件去安装依赖。 除非你手动更改依赖版本号,可能就会出现不兼容的情况。 总结来说就是: 规范兼容按照**lock**下载依赖。 不兼容按照**package.json**下载依赖,并且最后更新lock文件。

这里有个问题就是怎么来判断两个依赖的版本是否兼容? 这里需要知道一个知识点,什么是semver? 官方文档

如果没有package-lock.json文件,那么就会按照package.json文件去进行依赖树的构建。​

构建依赖树的时候,遵循扁平化的原则,也就是会优先将依赖放在node_modules的根目录下。后面在安装其他依赖的时候,会判断该依赖是否已经存在,如果存在的话,就会比较两个依赖的版本规范是否兼容,如果兼容则跳过该依赖的安装(忽略该依赖,因为已经存在),如果不兼容的话,会将该版本的依赖单独放在其父级的node_modules

然后在获取依赖资源的时候会优先考虑缓存,这样可以加快依赖的下载速度。​

npm依赖缓存策略

我们可以通过下面的命令来获取到缓存地址,我们可以在对应的__caches文件夹里查看相关文件。

npm config get cache
复制代码

那在我们每次install的时候都是怎么进行缓存的读取的呢?

在我们install的时候,npm会先将资源下载到缓存当中,然后才会解压的项目对应的node_modules中。

之后在每次安装资源的时候都会按照package-lock.json文件中的versionintegrityname信息来生成一个key值,这个key值可以命中index-v5中的缓存资源的信息。如果命中缓存了,就会找到对应的tar包,解压到项目中的node_modules中。​

这里其实可以探究一下这个key值是怎么生成的? 留一个思考:就是如果没有lock文件,是不是就意味着不会从缓存里拿资源了?而是每次都通过网络下载?

npm依赖管理机制

首先我们来看一下v2版本的npm依赖管理是怎么做的。

当一个项目中有AB两个依赖的时候,会在node_modules中依次安装这两个依赖。 并且这两个依赖都有一个共同的依赖项C,那么在v2中就会在AB文件夹的node_modules中各自安装C

npm-install.png

这样就会造成一个问题,那就是依赖地狱。

  1. 依赖地狱会造成内存资源的浪费
  2. 而且重复安装依赖,会造成安装进度缓慢

为了解决这样的问题,npmv3开始,就采取了扁平化的结构(其实当前npm很多机制都是借鉴了yarn的设计)。

在扁平化的结构下,npm是怎么进行管理依赖的呢?我们接下来一步步屡清楚。 首先依赖A 有一个依赖项C 版本号为v1,那么在安装依赖的时候就是这样的: 

image.png

然后在安装依赖B的时候,他也依赖v1版本的C,那么他就会从node_modules根目录中寻找该依赖,此时的依赖结构如下:

image.png

那么如果依赖B,它依赖的C版本是V2,那么结构就会发生变化,B会在自己目录下的node_modules安装对应v2版本的C:

image.png

根据上面的这种情况,继续往下看如果此时我们需要升级依赖Av2,该版本的A,不再依赖v1版本的C,而是依赖V2版本的C。那么此时npm会怎么做呢?

  1. 删除A
  2. 因为v1版本的C已经没有包依赖了,所以也会删除
  3. 安装v2版本的A
  4. 因为此时根目录下没有v2Cv2版本的C会安装在根目录下

image.png

到这里可能有个问题,为啥都依赖v2版本的C,依赖B还要在自己的目录下单独安装v2C

因为B依赖是安装的,安装B的时候已经在根目录里存在了v1版本的C的包,所以v2版本就安装在了它自身的目录。

从这里就可以看出,npm里依赖的安装顺序对依赖结构的影响会非常大,可能会影响node_modules的文件大小。

那么我们有办法让它完全扁平化吗?

当然是可以的,npm提供了一个命令,可以帮助我们处理这些重复文件,也可以理解为帮我们扁平化

npm dedupe
复制代码

执行之后结构就变成了更优雅的形式:

image.png

这里值得一提的是,yarn在安装依赖的时候会自动执行dedupe命令,帮我们自动拍平。

这里给大家看一个实际案例,我初始化了一个新的项目,这个项目只安装了一个依赖find-css-import(这个包是我写的,所以比较熟悉),这个包是只有一个依赖strip-comments v2.0

当我们首次安装这个依赖的时候,项目中的node_modules文件夹就会一次出现这两个文件。

QQ20211019-170429-HD.gif

这种现象也是符合上面我们分析的结果的。

然后我们手动的去改一下这个目录结构,把strip-comments文件夹放到find-css-importnode_modules中去,然后在执行一下dedupe来模拟一下扁平化的这个过程。

手动修改后的的目录结构是这样的: 

image.png

然后我们去执行一下dedupe

可以看到它成功的将文件结构给拍平了~

总结

这篇文章其实是一篇笔记,对自己这两天看到的知识进行一个归纳总结。

其实说起来想包管理工具虽然日常我们经常使用,但是有很多细节都是忽略的,也是希望通过这篇文章来捡起来一些东西。

参考

  • LucasHC(侯策)老师 - 前端基础建设与架构30讲
  • 山月老师 - 什么是semver

文章始发与公众号:前端程序喵,欢迎大家关注

image.png

文章分类

前端

文章标签

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

npm相关机制解析 的相关文章

  • ubuntu克隆ue4源码

    ubuntu克隆ue4源码 1 进入ue官网 xff0c 登陆自己账号 xff0c 进入个人账户界面 xff0c 点击连接 xff0c 账户 xff0c 关联github Epic Games 2 之后按照操作进行 xff0c 关联自己的g
  • Windows环境跑通清华开源通用时间序列分析模型TimesNet

    1 需要按照给定配置准备python3 8环境与相关依赖包 xff0c 全程在windows环境下进行 2 github thuml Time Series Library A Library for Advanced Deep Time
  • 嵌入式工程师职业生涯该怎样规划

    嵌入式工程师分布在各行各业 xff0c 包括消费电子 工业电子 汽车电子和军用电子等 从功能上面看 xff0c 嵌入式本身包括了51 mcu soc soc 43 baseband等很多形式 从开发的结构上看 xff0c 有些同学专注于底层
  • 使用ros实现c++与python通信

    创建工作空间 选择在桌面创建 cd mkdir p my workspace src 编译工作空间 cd my workspace catkin make source一下新生成的setup bash文件 xff1a source deve
  • C++输出系统时间

    编译软件 xff1a dev5 4 0 程序功能 xff1a 输出系统时间 xff0c 输出格式 2018 08 10 15 14 40 方法 xff1a 使用time t获取系统时间 xff0c 再使用strftime 函数对日期和时间进
  • 该博客已搬家至 博客园

    由于CSDN不支持metaweblog xff0c 该博客今日起停止更新 所有内容移至博客园 我的博客园博客地址 xff1a 戳我 https www cnblogs com wittxie CSDN写文章真的难受 xff0c 具体原因你们
  • Kernel Based Progressive Distillation for Adder Neural Networks:基于核的渐进式蒸馏的加法神经网络

    2020 NeurIPS AdderNet基于核的渐进式的蒸馏加法神经网络 一 简介二 问题解决2 1问题提出2 2初步解决方案2 3具体分析2 4问题解决 用核方法来解决这个问题2 5渐进式学习 三 实验结果分析3 1基于MNIST数据集
  • 人脸识别 灰度化

    人脸识别 灰度化 欢迎使用Markdown编辑器 你好 xff01 这是你第一次使用 Markdown编辑器 所展示的欢迎页 如果你想学习如何使用Markdown编辑器 可以仔细阅读这篇文章 xff0c 了解一下Markdown的基本语法知
  • 基于STM32F103的红外遥控小车

    本人小白一个 xff0c 利用空闲时间 xff0c 做了一些小东西 xff0c 跟大家分享一下自己的代码 如有不对的地方 xff0c 还请各位前辈指正 话不多说 xff0c 先上干货 include 34 remote h 34 inclu
  • 关于realsense d435i的安装步骤及问题总结

    一 realsense的安装过程 参考链接 xff1a 1 Ubuntu18 04 安装D435i ROS 2 Ubuntu下Realsense SDK的安装 3 Realsense D435i 在ubuntu上安装SDK与ROS Wrap
  • ROS编译catkin_make的时候报错找不到xxx.h头文件

    报错内容 xff1a home firefly eai ws src square square goal service src service server cpp 3 53 fatal error square goal servic
  • Ubuntu下安装GParted并分区,进行虚拟机内存扩展

    首先对于虚拟机下的Ubuntu系统安装Gparted 直接使用sudo apt get install gparted 关机先进行内存分配后 xff0c 再进行下面操作 网上还有其他适合的教程 xff0c 我的16 04这样安装是没问题的
  • PIP版本过低,更新无用,Command “python setup.py egg_info“ failed with error code 1 in报错

    Ubuntu下pip install 时候python2 7总是报错 Complete output from command python setup py egg info Traceback most recent call last
  • 小觅双目相机进行ROS标定

    安装image pipeline包 使用ROS官方提供的 camera calibration 包对双目相机进行标定 详情可见官网camera calibration Tutorials StereoCalibration ROS Wiki
  • ubuntu18.04安装ORB_SLAM3以及遇到的问题

    目录 1 安装c 43 43 11 2 安装Pangolin a xff09 安装依赖 b xff09 编译pangolin 切换到pangolin下载包里面 3 安装opencv 4 eigen3安装 5 boost安装 6 编译ORB
  • 【论文写作】Word中公式快捷输入方式

    环境 Win10 64位 用到软件 Mirsoft Word MathType Mathpix snipping tool Quicker 说明 xff1a 点击链接可以直达官网 一 前言 针对Word中公式输入效率低的问题 xff0c 本
  • 练习7-10 查找指定字符 (15分)

    本题要求编写程序 xff0c 从给定字符串中查找某指定的字符 输入格式 xff1a 输入的第一行是一个待查找的字符 第二行是一个以回车结束的非空字符串 xff08 不超过80个字符 xff09 输出格式 xff1a 如果找到 xff0c 在
  • 用cropper.js裁剪图片并上传到服务器,解析base64转存图片到本地

    今天要写上传图片功能 xff0c 研究了一下cropper 将图片上传服务器并保存到本地 html lt html gt lt head gt lt title gt 基于cropper js的图片裁剪 lt title gt lt met
  • 通讯协议详解

    1 xff0c 概念 网络协议指的是计算机网络中互相通信的对等实体之间交换信息时所必须遵守的规则的集合 网络上的计算机之间是如何交换信息的呢 xff1f 就像我们说话用某种语言一样 xff0c 在网络上的各台计算机之间也有一种语言 xff0
  • 自动识别击打控制系统

    目录 摘 要 关键词 一 系统方案 1 1 系统基本方案 1 2 程序算法的具体流程 二 视觉程序识别框架 2 1多线程 2 2 opencv配置文件 2 3 主函数 三 装甲板识别算法 3 1 装甲板识别 3 2 识别函数介绍 四 目标位

随机推荐