没想到你是这样的npm install

大家好,我是若川。今天给大家推荐一篇关于 npm install 的好文。很快能看完。

点击下方卡片关注我、加个星标
学习源码整体架构系列、年度总结、JS基础系列


前言

项目中执行npm install发生了什么,众所周知,执行npm install时会在当前项目目录的node_modules中安装依赖。并且将依赖项的层级关系保存在package-lock.json中。那么依赖项的层级关系是怎么确认的?依赖项之间是否存在区别?有无package-lock.json在安装时有什么区别呢?笔者希望借以此文可以和读者们一起厘清npm install

工欲善其事必先利其器,先一起来了解下npm install

npm-install

常用的命令包含(具体含义和执行效果会在下文说明)

  • npm install

  • npm install -P|--save-prod

  • npm install -D|--save-dev

  • npm install -O|--save-optional

  • npm install --no-save

aliases: npm i, npm add

npm install这个命令会在项目路径下安装一个或多个依赖包,如果项目中存在package-locknpm-shrinkwrapyarn.lock文件。那么安装过程将就基于这些文件。其优先级为:

  • npm-shrinkwrap.json

  • package-lock.json

  • yarn.lock

其中npm-shrinkwrap.jsonnpm 5之前的依赖锁定文件,其在npm 5后被package-lock.json替换。两个文件功能类似,最大的不同是npm-shrinkwrap.json需要执行npm shrinkwrap来初始化生成,而package-lock.json为自动生成。本文撰写时npm使用的版本为v6.14.5,故下文所有样例均在此版本下做交流讨论。其他版本任何问题欢迎留言讨论。yarn.lockyarn cli的产物,不在此文章讨论。

npm install执行时会解析package.json中定义的依赖关系,进而根据package.json生成package-lock.json依赖锁定文件。package.json中的依赖关系可以由开发人员自行定义,也可使用npm install [--optional]来指定存储位置,或使用npm install --no-save不进行存储。

自古习物先习源。package.json中是那些在影响依赖树呢?

package.json

package.json文件是项目的描述文件,包括项目的nameversiondescription等很多字段。但真正影响依赖树的并不多,包括dependenciesdevDependenciespeerDependenciesoptionalDependenciesbundledDependencies。下面一起来看下他们区别和使用场景。

dependencies:主要依赖

dependencies是主要依赖。也即必须依赖。由包名和版本区间映射成的简单 json对象组成。版本区间由一个或多个分隔符组成。是项目运行、打包的主要依赖。执行npm install时会从上至下递归安装dependencies及其内部依赖。并将解析的依赖树存储在package-lock.json中。会随版本一起发布到npm库。是最重要的依赖节点。

执行npm install -P|--save-prod会将指定包放入此节点。

常用的dependencies如:axiosfetch等。

{"dependencies": {"axios": "^0.21.1","fetch": "^1.1.0"}
}

devDependencies:开发依赖

devDependencies是开发环境的依赖。其格式同dependencies,开发人员本地执行npm install时也会从上至下递归安装devDependencies及其内部依赖。并将解析的依赖树存储在package-lock.json中。也会随版本一起发布到npm库。但是不同的是。非开发人员通过项目安装依赖时。也就是包安装后出现在node_modules中时,devDependencies不会被安装,也不会出现在项目的package-lock.json中。

所以在开发时,dependenciesdevDependencies区别并不大,但是作为依赖包被其他项目引入时,只有dependencies中的依赖会被解析成依赖树并下载。devDependencies中的依赖会被忽略。

执行npm install -D|--save-dev会将指定包放入此节点。

常用的devDependencies如:karmamochawebpack

{"devDependencies": {"karma": "^1.3.0","mocha": "^5.2.0","webpack": "^1.13.1","webpack-dev-server": "^1.14.1"}
}

peerDependencies:同等依赖

peerDependencies是同等依赖。其格式同dependencies。主要在开发包时使用,常规开发项目不建议使用。比如某些情况下开发人员为了表明在不同系统和运行环境下的兼容性,即非所有情况下都是必要的依赖。就会通过peerDependencies来表明。peerDependencies中更像是当前包所依赖是插件。peerDependencies里面的依赖会随版本一起发布,但是不会自动安装,需要开发和使用人员手动安装。(npm v7下会默认安装)

eslint-plugin-prettier会同等依赖eslintprettier。即eslint-plugin-prettier需要在eslintprettier都安装时才会生效。但是其自身并不会强制安装eslintprettier。而是会通过警告的方式提示开发者。

`eslint-plugin-prettier requires a peer of xxx but none is installed. You must install peer dependencies yourself`

如果不想在未安装peerDependencies的情况下提示警告。可以通过peerDependenciesMeta设置optionaltrue来关闭警告。

{"peerDependencies": {"eslint": ">=5.0.0","prettier": ">=1.13.0"},"peerDependenciesMeta": {"eslint": {"optional": true}}
}

optionalDependencies:可选依赖

optionalDependencies是可选依赖。其格式同dependencies。当需要某些依赖在安装失败时不会阻塞项目的运行和打包,就可以使用optionalDependencies来定义。optionalDependencies里面的依赖会随版本一起发布,且会自动安装。可以使用npm install --no-optional命令来跳过安装。

执行npm install -O|--save-optional会将指定包放入此节点。

optionalDependencies使用需要开发者在项目中作兼容。如:

try {var foo = require('foo')var fooVersion = require('foo/package.json').version
} catch (er) {foo = null
}if ( notGoodFooVersion(fooVersion) ) {foo = null
}// .. then later in your program ..if (foo) {foo.doFooThings()
}

bundledDependencies:绑定依赖

bundledDependencies是绑定依赖,其值是一个数组。在发包时定义绑定包。常规项目中使用的并不多。和npm install的也并无关系,所以在此不做过多介绍。值得一提的是,使用bundleDependencies也是可以的。

{"name": "awesome-web-framework","version": "1.0.0","bundledDependencies": ["renderized","super-streams"]
}

了解了package.json中影响依赖树的节点,那么接下来就是重头戏npm install登场了~

一、无依赖冲突

最简单的场景莫过于此,当项目的package.json的依赖及其子 依赖间没有冲突时,即A依赖B、C、D。表示为A[B、C、D]。则依赖会平铺在node_modules下。即使有多个相同的依赖,只要版本不存在冲突,就都符合当前场景。

举个例子。fetch-demo2项目中值依赖fetch这一个包。

{"name": "fetch-demo2","version": "1.0.0","description": "","main": "index.js","dependencies": {"fetch": "^1.1.0"},"devDependencies": {},"scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC"
}

此时执行npm i,会得到如下的目录结构的node_modules

可得到依赖树(根据package-lock.json分析得出)

不难得出以下结论。当项目中的依赖无冲突时,项目依赖及其内部依赖会平铺在一级node_modules中。

二、项目顶级依赖存在冲突

顶级依赖即项目package.json中的依赖。

当项目顶级依赖存在冲突时,会将顶级依赖放在node_modules中的一级目录下,冲突的包放在自己的node_modules下。为了模拟这种场景,将biskviit@2.0.0放在fetch-demo2项目的顶级依赖上。

{"dependencies": {"fetch": "^1.1.0","biskviit": "2.0.0"}
}

执行npm install后查看node_modules的目录结构

分析依赖树

可以看出在顶级依赖biskviit@2.0.0和内部依赖biskviit@1.0.1存在冲突时,顶级依赖会占据node_modules的一级目录,内部依赖则会存储在其内部的node_modules

三、项目内部依赖存在冲突

当项目的内部依赖存在冲突时,会先检测一级node_modules是否存在依赖包,不存在则存储,如果存在判断是否有版本冲突,无冲突则使用一级node_modules的依赖包,有冲突则存储在自身的node_modules中。还是举例说明下。

一级node_modules无冲突包

发布自定义新包conflict-lbywer@1.0.0npm。其依赖为

{"dependencies": {"biskviit": "^2.0.0"}
}

fetch-demo2项目的顶级依赖改为

{"dependencies": {"conflict-lbywer": "1.0.0","fetch": "^1.1.0"}
}

删除node_modulespackage-lock.json后,执行npm i后,查看目录结构

分析依赖树

可以看出conflict-lbywer所依赖的biskviit@2.0.0fetch所依赖的biskviit@1.0.1冲突时,在顶级依赖没有biskviit的情况下,将biskviit@2.0.0安装到了顶级依赖。

如果将顶级依赖中的conflict-lbywerfetch更换顺序呢,依赖包顺序是否会发生变化,我们一起来研究。

修改顶级依赖

{"dependencies": {"fetch": "^1.1.0","conflict-lbywer": "1.0.0"}
}

删除node_modulespackage-lock.json后,执行npm i后,查看目录结构

分析依赖树

可以看出在调整conflict-lbywerfetch顺序后,目录结构并无变化。所以可得出结论,在一级node_modules不存在冲突包时,会将高版本的包放在一级node_modules中。低版本的放到内部的node_modules中。

一级node_modules有冲突包

如果一级node_modules有冲突包时,情况又会如何呢?

删除顶级依赖中的conflict-lbywer

{"dependencies": {"fetch": "^1.1.0"}
}

删除node_modulespackage-lock.json后,执行npm i后,查看目录结构

分析依赖树

顶级依赖添加conflict-lbywer@1.0.0

{"dependencies": {"fetch": "^1.1.0","conflict-lbywer": "1.0.0"}
}

直接执行npm i后,查看目录结构

分析依赖树

可以发现,在依赖树无变化的情况下,node_modules的目录结构是不一样的。所以可以得出结论,在一级node_moudles已经存在依赖包的情况下,新安装的依赖包如果存在冲突,会安装到内部的node_modules中。

四、存在package-lock.json

这种情况也很简单,npm install会完全按照package-lock.josn的层级结构下载安装依赖包

删除node_moudles后,执行npm install

直接执行npm install后,查看目录结构

分析依赖树

可以发现,在存在package-lock.json的情况下,node_modules的目录结构是稳定的。

结语

上文对执行npm install时,一些常见的情况做了测试和分析,也给出了相应的结论。欢迎读者们批评斧正。也欢迎打赏点赞哦~

参考文献和链接

  • https://docs.npmjs.com/cli/v7/commands/npm-install

  • https://docs.npmjs.com/cli/v7/configuring-npm/package-json

  • https://docs.npmjs.com/cli/v7/configuring-npm/folders


最近组建了一个江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你进群。


今日话题

略。欢迎分享、收藏、点赞、在看我的公众号文章~

一个愿景是帮助5年内前端人走向前列的公众号

可加我个人微信 ruochuan12,长期交流学习

推荐阅读

我在阿里招前端,我该怎么帮你(可进模拟面试群)

2年前端经验,做的项目没技术含量,怎么办?

点击方卡片关注我、加个星标

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》多篇,在知乎、掘金收获超百万阅读。

从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。

同时,活跃在知乎@若川,掘金@若川。致力于分享前端开发经验,愿景:帮助5年内前端人走向前列。

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

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

相关文章

Django——Model

一、 ORM 在 MVC 或者说 MTV 设计模式中,模型(M)代表对数据库的操作。那么如何操作数据库呢? 我们可以在 Python 代码中嵌入 SQL 语句。 但是问题又来了,Python 怎么连接数据库呢?可以使用类似 pymysql 这一…

大理石在哪儿_如何创建用户体验写作课程而又不失大理石

大理石在哪儿I’m a UX Writer. It’s a designated human on the software development team who writes words for interfaces. All the words. From the tiniest tooltips to navigation, to buttons, to errors, and so on, ad infinitum. UX writing is less writing and …

Vuex 源码还有一些缺陷?

我看了vuex3和vuex4的源码也输出了文章,看到这篇时,vuex还有缺陷?看了看确实是好文,不愧是大佬写的。文章不算长,推荐给大家看看。点击下方卡片关注我、加个星标学习源码整体架构系列、年度总结、JS基础系列众所周知&a…

三级菜单页面布局_三级菜单的最快导航布局

三级菜单页面布局重点 (Top highlight)When users navigate an interface, there’s a need for speed. The faster it is for them to find what they’re looking for, the more time they’ll save on their task.用户导航界面时,需要提高速度。 他们找到所需内容…

ux体验网站 英国_定义网站图像时的UX注意事项

ux体验网站 英国As the saying goes —俗话说 - “A picture is worth a thousand words.”“一张图片胜过千言万语。” When creating content on the web, it’s often recommended to be using high-quality imageries and making sure that the images serve its purpose …

iconfont 支持全新的彩色字体图标

大家好,我是若川。iconfont我相信大家都用过,而现在支持全新的彩色字体图标了。这是第二次转载,上一次的好文是2020 前端技术发展回顾。点击下方卡片关注我、加个星标学习源码整体架构系列、年度总结、JS基础系列一直以来,Web 中想…

出色的社区网站_《最后的我们》中出色的制作系统

出色的社区网站游戏设计分析 (GAME DESIGN ANALYSIS) The Last of Us became an instant classic the day it was released, back in 2013. At the sunset of the sixth console generation, it felt like Naughty Dog managed to raise the bar in all critical areas of game…

入坑 Electron 开发跨平台桌面应用

‍作为一个跨平台的桌面应用开发框架,Electron 的迷人之处在于,它是建立在 Chromium 和 Node.js 之上的 —— 二位分工明确,一个负责界面,一个负责背后的逻辑,典型的「你负责貌美如花,我负责赚钱养家」。上…

java 接口编程_JAVA面向接口编程

一、什么是面向接口编程要正确地使用Java语言进行面向对象的编程,从而提高程序的复用性,增加程序的可维护性、可扩展性,就必须是面向接口的编程。面向接口的编程就意味着:开发系统时,主体构架使用接口,接口…

小程序 显示细线_精心设计:高密度显示器上的细线

小程序 显示细线Despite the many benefits of Retina displays, there is one clear drawback that must be considered when designing for high-density screens:尽管Retina显示器具有许多优点,但在设计高密度屏幕时仍必须考虑一个明显的缺点: 必须避…

React 入门手册

大家好,我是若川。推荐这篇可收藏的React入门手册。也推荐之前一篇类似的文章《如何使用 React 和 React Hooks 创建一个天气应用》。点击下方卡片关注我、加个星标React 是目前为止最受欢迎的 JavaScript 框架之一,而且我相信它也是目前最好用的开发工具…

根号 巴比伦_建立巴比伦卫生设计系统

根号 巴比伦重点 (Top highlight)In this post I’ll explain the first phase of creating our Babylon DNA, the design system for Babylon Health, and how we moved the Babylon design team from Sketch to Figma.在这篇文章中,我将解释创建巴比伦DNA的第一阶…

《Migrating to Cloud-Native Application Architectures》学习笔记之Chapter 2. Changes Needed

2019独角兽企业重金招聘Python工程师标准>>> Cultural Change 文化变革 A great deal of the changes necessary for enterprise IT shops to adopt cloud-native architectures will not be technical at all. They will be cultural and organizational changes t…

前端,你要知道的SEO知识

大家好,我是若川。三天假期总是那么短暂,明天就要上班了。今天推荐一篇相对简单的文章。点击下方卡片关注我、加个星标之前有同学在前端技术分享时提到了SEO,另一同学问我SEO是什么,我当时非常诧异,作为前端应该对SEO很…

高安全性同态加密算法_坏的同态性教程

高安全性同态加密算法I was going to write at length about the issues I see in neumorphism and why this trend should be avoided. I know any attempt to guide my most impressionable colleagues away from it, will end up being failing because this fad is going t…

前端容易忽略的 debugger 调试技巧

大家好,我是若川。我们日常开发碰到的很多问题,通过 debugger 都能快速定位问题,所以推荐这篇大家容易忽略的调试技巧。会定位问题,可以节省很多时间。也就是我经常说的工欲善其事,必先利其器。也是为什么我经常强调调…

Spring高级程序设计这本书怎么样

关于Spring高级程序设计 评论读后感:这本书需要有一定的spring基础的人看读后感:对于了解Spring 很有用,并且是一本不错的参考书读后感:这本书早就想买了,就是太贵了~~~ 啦啦啦&…

玉伯:开源有带给我什么

在2021年527蚂蚁技术日上,蚂蚁内源社区举办了内源专场,在专场上玉伯给大家分享了《开源有带给我什么》,以下为演讲的图文整理。我的开源之路我从2009年到2018年,接近十年时间,一直在做开源的一些事情,在这个…

python并行运算库_最佳并行绘图Python库简介:“ HiPlot”

python并行运算库HiPlot is Facebook’s Python library to support visualization of high-dimensional data table, released this January. It is particularly well known for its sophisticated interactive parallel plot.HiPlot是Facebook的Python库,用于支持…

Asp.net 文件上传的 FileUpload FileName 和 FileUpload PostedFile.FileName的细节问题

Asp.net 文件上传的 FileUpload FileName 和 FileUpload PostedFile.FileName的细节问题 ASP.NET 文件上传估计大家都用得很熟悉,常用控件 FileUpload 。 主要步骤: 1.判断是否合法 2.获得文件的路径 (包括目录的完整路径,同时可能…