本文分享自华为云社区《运行npm install命令的时候会发生什么?》,作者: gentle_zhou。

npm(node package manager),是随同Node.js一起安装的第三方包管理器;通过npm,我们可以安装、共享、分发代码,管理项目的依赖关系。

我们日常在下载第三方依赖的时候,都会用到一个命令npm install,然后依赖包就会被安装到node_modules目录下;但是我们在运行这个命令的时候,都会发生什么呢?带着好奇心,我去调研学习了一番。

大致的流程是:npm install命令输入 > 检查node_modules目录下是否存在指定的依赖 > 如果已经存在则不必重新安装 > 若不存在,继续下面的步骤 > 向 registry(本地电脑的.npmrc文件里有对应的配置地址)查询模块压缩包的网址 > 下载压缩包,存放到根目录里的.npm目录里 > 解压压缩包到当前项目的node_modules目录中。

(上面的图片就显示了项目中依赖如果过多的尴尬:等待时间过长,下载下来依赖过多导致node_modules过大)

下面会介绍一下npm处理依赖的早前和当前的方式 以及 几种不同的install命令下载方式。

早期版本:递归

在npm早期版本里,npm处理依赖的方式很粗暴简单。它会严格按照根目录下package.json文件的结构以及各个子依赖包的package.json文件的结构,递归地把依赖安装到它们各自的node_modules目录里。这样如果是个小项目,只需要几个依赖且这些依赖不会依赖别的依赖,那么这样的树形结构就还算清晰明了(node_modules的结构与package.json里的结构一一对应且层级结构明显)。

但如果我们的项目是个大项目,里面的依赖非常多(导致嵌套层级非常深),且不同的层级可能会引用同一个依赖(导致重复冗余),就不是我们想要的情形了。

当前版本:扁平化

于是,为了解决以上递归管理依赖带来的问题,npm在 3.X版本里做了一次更新,引入了扁平化管理(dedupe)的方式。dedupe是dedeplicated的缩写,即duplicates were remove,把重复的移除。

扁平化管理的思路就是首先遍历package.json文件下dependenciesdevDependencies字段里的依赖,作为依赖树的根节点;然后在每个根节点依赖下面都会有其依赖的依赖,作为其子节点;npm会开启多进程从每个根节点开始逐步往下寻找更深层次的节点。而package.json文件下dependenciesdevDependencies字段里的依赖会被安装在node_modules根目录下。在遍历这些依赖的时候,如果发现有重复的依赖模块(重复:模块名相同且semantic version兼容;这里的兼容,是指语义化版本都会有一段版本允许范围,如果两个依赖的版本号是在这个范围交际里就说明是兼容;比如依赖X依赖于依赖Y@^1.0.0,而依赖Z依赖于依赖Y@^1.1.0,则Y@^1.1.0就是兼容版本),就直接将其丢弃。

但是如果仅仅这样,其实也有风险。在大项目中,很有可能会碰到依赖A依赖于依赖C-1.0版本,依赖B依赖于依赖C-2.0版本;而在执行npm install命令的时候,会按照package.json里面的依赖顺序依次解析,因此依赖C-1.0和依赖C-2.0的在文件里的放置顺序会导致Node_modules的依赖结构产生变化。而且为了让开发者可以使用最新的依赖包,package.json文件里通常只会锁定大版本(即文件里依赖如果是^1.1.0版本,npm就会去仓库中获取符合1.x.x形式的最新版本),因此某些依赖包小版本更新后,也会造成依赖结构的改变。所以,为了解决npm install命令导致的这种不确定问题,npm 5.x版本里还新增了package-lock.json文件。

package-lock.json文件可以保证每次执行npm install后生成的node_modules目录结构一定是完全相同的。下图就是package-lock.json中其中一个依赖的信息,有name-包名,version-包的版本号,dependencies-和node_modules中包结构一一对应的对象,resolved-包具体的安装来源,integrity-包的hash值,requires-对应子依赖的依赖:

注:并不是所有的子依赖都有dependencies这个属性,只有子依赖的依赖和当前已安装在根目录的Node_modules中的依赖起了冲突之后,才会有这个属性。

置于为何说package-lock.json 文件 和 node_modules 目录结构是一一对应的。还是举刚刚前面提及的那个依赖冲突导致依赖结构产生变化的例子,“依赖A依赖于依赖C-1.0版本,依赖B依赖于依赖C-2.0版本”,此时因为package-lock.json文件的存在,我们会把依赖C-1.0版本安装在依赖A的node_modules目录下(对应依赖A在package.json文件里的dependencies属性),依赖C-2.0版本安装在根目录下。这可以保障每次安装生成的依赖目录结构保持相同。

package-lock.json 文件还有个优点,就是它会缓存每个包的具体版本和下载链接,在后期再去install的时候,就不需要再去远程仓库进行查询操作了,减少了大量网络请求。

几种不同的install命令下载方式

  1. npm install xxx #(XXX是某依赖包)安装依赖模块至项目node_modules目录下,不会修改package.json文件里的内容
  2. npm install -g xxx #安装依赖模块到全局(而不是项目node_modules目录下),不会将该依赖模块写到package.json文件里的dependenciesdevDependencies字段里
  3. npm install --save xxx #安装依赖模块到项目node_modules目录下,并将依赖写入到package.json文件里的dependencies字段中;该依赖是开发和生产环境里都需要的
  4. npm install --save-dev xxx #安装依赖模块到项目node_modules目录下,并将依赖写入到package.json文件里的devDependencies字段中

点击关注,第一时间了解华为云新鲜技术~​

运行npm install命令的时候会发生什么?相关推荐

  1. 当运行npm install 命令的时候带上ignore-scripts,会发生什么?

    摘要:运行npm install 命令的时候带上ignore-scripts, 可以避免一个恶意包里的病毒. 本文分享自华为云社区<运行npm install 命令的时候带上--ignore-s ...

  2. 运行npm install命令后的执行过程

    发出npm install命令 npm向registry查询模块压缩包的下载地址 下载压缩包并存放到本地npm缓存路径(~/.npm目录) 解压到当前项目node_modules目录 如果你没联网,n ...

  3. 运行npm install webpack -g 出现 4048错误

    经过笔者网上查资料,百度等再三验证发现问题所在: win11系统出现这种情况只是因为权限不够,用管理员权限打开命令行,运行:运行npm install webpack -g 就会安装成功:

  4. 前端开发:项目运行npm install 提示XXX packages are looking for funding run `npm fund` for details的解决方法

    分享一个去年遇到的问题,作为总结性的来分享一下,方便有需要的人查看使用,具体操作是这样的:更新了依赖,更新完之后,运行npm: 命令行:npm install 然后提示如下信息: 35 package ...

  5. run `npm fund` for details解决,前端开发:项目运行npm install 提示XXX ...for funding run `npm fund`...的解决方法

    run npm fund for details解决,前端开发:项目运行npm install 提示XXX -for funding run npm fund-的解决方法 35 packages ar ...

  6. clone别人远程仓库的代码,运行npm install报错npm ERR! Maximum call stack size exceeded

    运行npm install报错,我是实习生,实习第四天就各种出错,多人合作的时候连clone下来的仓库,运行npm install时都出错:npm ERR! Maximum call stack si ...

  7. 1.运行npm install 时,卡在sill idealTree buildDeps没有反应

    项目场景: 运行npm install 问题描述 运行npm install 时,卡在sill idealTree buildDeps没有反应 fetchMetadata: sill mapToReg ...

  8. npm install命令运行中出现Error: ENOENT: no such file or directory解决方法

    在开发过程中执行下面脚本出现错误 npm install --save ng-bootstrap/ng-bootstrap 出现 Error: ENOENT: no such file or dire ...

  9. mac 终端上运行NPM INSTALL时出现问题:npm error!cb() 从未调用过!解决了

    在使用Node PackageModels(npm install)时,遇到此错误: 在使用 vue init webpack my-project生成一个基于 webpack 模板的新项目时,报下面 ...

最新文章

  1. Telltale:看Netflix如何简化应用程序监控体系
  2. IDEA:com.intellij.execution.ExecutionException: not found for the web module.
  3. 携程高管解读Q3财报:海外市场Trip.com流量恢复到去年同期70%
  4. mysql教程查询语句_最全的mysql查询语句整理
  5. 多路复用IO: select、sys_select、do_select源码分析
  6. java反显是什么_卡西欧反显是什么意思
  7. python二维列表转字典_在Python中字符串、列表、元组、字典之间的相互转换
  8. VMware vSphere ESX 迁移到 ESXI 指南
  9. Python之认识世界
  10. 《算法竞赛入门经典》习题及反思 -2
  11. 【ML小结4】深入了解SVM
  12. PLSQL下载及安装参照
  13. 手机关机的java代码_Android关机界面代码
  14. XShell免费正版远程控制ssh客户端
  15. 多边形的单边裁剪算法-JS
  16. mysql导入pet表
  17. JNLP说明(good)
  18. 阿里云BaaS下蚂蚁区块链开发实践(一)
  19. 神经网络——PRML
  20. 软件安全测试-软件安全测试概述

热门文章

  1. android 印度语_为什么发展印度语维基百科至关重要
  2. perl 序列化_对Perl的热爱团结了多元化的社区
  3. pdf编辑 开源_新闻编辑室看到了开源的光芒
  4. (45)css面试题集锦二
  5. HTML5 header元素
  6. Bootstrap HTML编码语法规范
  7. CSS 文本转换 text-transform属性
  8. 视觉SLAM十四讲学习笔记-第二讲-开发环境搭建
  9. 深度学习笔记(40) YOLO
  10. 腾讯python面试题_面试题 | 腾讯数据分析面试题分享