npm install及其目录结构
npm install 安装包及其依赖。npm install: 默认情况下,安装package.json文件中列出的所有依赖。加-P或--production后,只安装dependencies列出的依赖,而不安装devDependencies列出的依赖。npm install [<@scope>/]<name>,安装包的最新版本,并记录在package.json中的dependencies中,加-D或--save-dev,安装包,并记录到devDependencies 中
npm install react
npm install @babel/core -D
npm install [<@scope>/]<name>@<version>: 安装指定版本的包
npm install react@16
npm install 安装依赖到什么地方呢?默认情况下,它会安装到当前包的根目录下的node_modules中。比如redux,它有自己的依赖,安装redux时,它的依赖就会安装redux的根目录下的node_modules中。

如果安装依赖的地方并不在一个包下,比如,开始一个新项目,要安装依赖,它只是一个普通的目录,那就安装到当前目录下的node_modules中。如果安装的依赖有scope,比如@babel/core, 它会安装到node_modules下的@scope目录下,相同的scope的包集中放到同一个目录下。安装完成后,可以通过require("packagename")来加载主模块(packae.json中main指定的文件),或 require("packagename/lib/path/to/sub/module") 加载其它模块。如果安装包的是命令包,比如webpack-cli,它里面的bin目录会链接到node_modules中的./bin目录下,当在package.json中的script写命令,然后使用npm run 执行时,npm 会找到相应的命令执行。其实,这里有一个小细节,当在一个目录中安装包时,npm会从当前目录向上查找,看有没有一个目录包含package.json文件或node_modules目录,如果有,它会在找到的目录中安包,npm认为这是一个有意义的目录。如果没有,则在当前目录安装包。比如项目根目录下,有packag.json, 你不小心 cd src中,此时在src目录下安装包,npm还是会把包安装到根目录。npm 安装包的时候,先安装到npm 的缓存中,然后再解压到node_modules中。
项目的依赖都安装到node_modules下,那node_modules的目录结构是怎么样的? npm 2版本的时候,以嵌套的方式安装所有依赖,比如App项目依赖A,A依赖B,那么App的node_modules中有A, A的node_modules中的B。这就会导致依赖树太深,并且安装的包大多,冗余。为了解决这个问题,npm 3版本则试图扁平化安装。主依赖和二级依赖安装到同级目录,主依赖就是package.json中列出的依赖,二级依赖就是主依赖的依赖。还是以项目App为例,主依赖就是A,二级依赖就是B,npm 3安装的时候,A和B在同一级目录,都是在App的node_modules中。

项目开发时,又安装了一个依赖C,C也依赖B,不过是2.0版本,如果是npm2安装,直接安装C依赖,C里面嵌套B。如果是npm3安装,它就是安装C,然后尝试把B安装到C同等级别的目录,也就node_modules顶级目录,但node_modules顶级目录下面已经有了B 1.0依赖,不能再安装B 2.0依赖,否则就冲突了,所以B2.0,只能安装到C目录下

在命令行窗口,它会如下显示

你会发现,目录结构没有办法显示依赖关系, 可以使用npm ls 命令,列出依赖及其关系,列出主依赖,则是 npm ls --depth=0
假设再安装依赖D,它也依赖Bv2.0,还是由于node_modules顶级目录中安装了B1.0, B2.0要安装到D下面,注意,这里和以后的安装都是npm3 了,

继续依赖E,E依赖B1.0,此时只安装E依赖,B依赖不用装了,因为在顶级目录中已经有了,

反应到命令行中就是

现在升级A 到2.0,正好它也依赖B2.0,首先是package.json 中A依赖的版本号从1.0 到2.0, 再在node_module中,删除掉A1.0,安装2.0,不能删除B1.0 因为E在用,最后安装B2.0

现在package.json中的依赖如下
"dependencies": {
"mod-a": "^2.0.0",
"mod-c": "^1.0.0",
"mod-d": "^1.0.0",
"mod-e": "^1.0.0"
}
此时,你觉得项目初始化完成了,就提交了。同事拿到新代码,就npm install,安装所有依赖,你会发现他安装的目录如下

安装顺序起起到到了重要的作用,npm install 先安装A2.0, 它依赖B2.0, 所以在node_modules顶级目录中安装了A2.0和B2.0,由于C和D都是依赖B2.0, 所以只在node_modules中安装C和D主依赖就可以了,B2.0已经存在了,安装E的时候,它由于依赖B1.0,所以在它的node_modules下面安装了B1.0.
当npm install 一个依赖的时候,它会从当前目录向上找,如果在祖先node_modules中找到符合的依赖,它就不会在本目录下安装,这也解决了循环依赖问题。但你会发现,你和你的同事的node_modules目录结构不一致了。npm3 这种安装依赖的方式,会导致一个问题,你的机器上的node_modules可能和你同事的node_modules 不一致,npm3 并不会已确定性的方式安装node_modules。如果项目中只依赖主依赖,那是没有影响的,如果有使用二级依赖,那就会有影响。比如 import {} from B, 你同事引用是B2.0, 而你引用的是B1.0. 怎么办?把node_modules删除了,重新安装。这也导致package-lock.json 文件出现。如果一个项目中有package-lock.json文件,npm install的时候,就会照package-lock.json文件列出的依赖树安装依赖,package-lock.json文件会记录项目开发时,依赖的安装顺序。比如A从1.0升级到2.0,package.json中只会把A升级到2.0,但package-lock.json 则会记录
{
"dependencies": {
"A": {
"version": "2.0.0",
"requires": {
"B": "2.0.0"
},
"dependencies": {
"B": {
"version": "2.0.0"
}
}
},
"B": {
"version": "1.0.0",
},
"E": {
"version": "1.0.0",
"requires": {
"B": "1.0.0",
}
}
}
}
可以清新地看到安装顺序,无论以后,谁按照package-lock.json文件安装,安装的目录都是一样的。

后面又出了yarn, yarn.lock文件,安装包的依赖时,如果包中有package-lock.json或shrinkwrap.json或yarn.lock这些文件, 它会以这些文件为依据,安装依赖。参考顺序是npm-shrinkwrap.json,package-lock.json,yarn.lock。
在上图的基础上,假设你现在继续开发,把E升级了,它依赖B2.0,npm 会删除掉E1.0,安装E2.0,删除掉B1.0,因为没有模块依赖它了,安装B2.0 到node_module顶级目录。

这时,又有一个问题,模块B2.0 在每一个目录中,为了移除冗余,可以使用 npm deque, 这个命令找到依赖B2.0的模块,然后,重定向到顶级目录中的依赖,然后删掉嵌套的依赖b2.0

npm install及其目录结构的更多相关文章
- 【VUE】Mac下vue 开发环境搭建,以及目录结构
1 安装Node.js 参看 node.js环境安装 http://www.cnblogs.com/richerdyoung/p/7265786.html 2 安装淘宝镜像 npm install ...
- 【vue iview】项目 win10 放在C盘 经常npm install不成功,就是因为 权限问题,把代码目录放到D盘就没事了。
[vue iview]项目 win10 放在C盘 经常npm install不成功,就是因为 权限问题,把代码目录放到D盘就没事了.
- nodejs npm install全局安装和本地安装的区别
npm的包安装分为本地安装(local).全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已,比如:代码如下:复制代码npm install # 本地安装npm install - ...
- 基于gulp编写的一个简单实用的前端开发环境好了,安装完Gulp后,接下来是你大展身手的时候了,在你自己的电脑上面随便哪个地方建一个目录,打开命令行,然后进入创建好的目录里面,开始撸代码,关于生成的json文件请点击这里https://docs.npmjs.com/files/package.json,打开的速度看你的网速了注意:以下是为了演示 ,我建的一个目录结构,你自己可以根据项目需求自己建目
自从Node.js出现以来,基于其的前端开发的工具框架也越来越多了,从Grunt到Gulp再到现在很火的WebPack,所有的这些新的东西的出现都极大的解放了我们在前端领域的开发,作为一个在前端领域里 ...
- Vue 入门之目录结构介绍
Vue 是一套用于构建用户界面的渐进式框架,与其它大型的页面框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合.另一方面,当 ...
- npm常用命令学习(npm install -D,semver版本规范, npm进行版本管理的最佳实践用法)
什么是npm npm有两层含义.一层含义是Node的开放式模块登记和管理系统,网址为npmjs.org.另一层含义是Node默认的模块管理器,是一个命令行下的软件,用来安装和管理Node模块. npm ...
- vue-cli3安装创建项目以及目录结构
安装脚手架cli3.0 全局安装 npm install -g @vue/cli 或 yarn global add @vue/cli 查看版本/是否安装成功 vue -V 如果你仍然需要使用旧版本的 ...
- React脚手架创建一个React应用以及项目目录结构详解
react脚手架 用来帮助程序员快速创建一个基于xxx库的模板项目,包含了所有需要的配置,指定好了所有的依赖,可以直接安装/编译/运行一个简单效果 react提供了一个专门用于创建react项目的脚手 ...
- React对比Vue(01 数据的定义,使用,组件的写法,目录结构等)
1.脚手架对比 两个都需要安装node node自带npm 然后安装cnpm yarn(有时候 npm会丢包,所以) npm install -g cnpm --registry=https://re ...
- vuejs目录结构启动项目安装nodejs命令,api配置信息思维导图版
vuejs目录结构启动项目安装nodejs命令,api配置信息思维导图版 vuejs技术交流QQ群:458915921 有兴趣的可以加入 vuejs 目录结构 build build.js check ...
随机推荐
- pageoffice6 实现在线模板套红
在Web项目中处理Word文档,经常会用到Word模板,只不过这里的"模板"概念,都是指在Web项目中预先放置的doc.docx等扩展名的.真正的Word文档,对于Excel和PP ...
- go语言开发的内网穿透工具,frp.
转载自:https://www.appinn.com/frp/ 什么是 Frp? 内网穿透工具有很多,其中 Frp (Fast Reverse Proxy) 是比较流行的一款.FRP 是一个免费开源的 ...
- Android OpenMAX(四)OMX Core
假设我们已经写好了所有的OMX组件,有vdec.venc.adec.aenc,接下来问题来了,我们应该如何管理这些组件呢(创建.销毁)?这一篇文章我们向上一层学习OMX Core提供的标准API. O ...
- SDL入门
本篇主要用于记录SDL2.0.22的基本用法,参考别人的代码,并加了注释方便理解这些api 以下两个demo可以在VS中编译并运行,代码参考 SDL视频显示_奋斗吧!骚年!的博客-CSDN博客 1.S ...
- FFmpeg中的关键方法及结构体(二)avformat_open_input
1.avformat_open_input 该方法声明在libavformat/avformat.h:2093 int avformat_open_input(AVFormatContext **ps ...
- 将编译过的C++库迅速部署在Visual Studio新项目中
本文介绍在Visual Studio中,通过属性表,使得一个新建解决方案中的项目可以快速配置已有解决方案的项目中各类已编译好的C++第三方库的方法. 例如,我们现有一个解决方案,其中的一个项目 ...
- 音视频学习-exceeded mem limit: ActiveHard 50 MB (fatal)
一.现象 ReplayKit2 适配中 UPLOAD进程被系统杀掉 日志中显示原因:exceeded mem limit: ActiveHard 50 MB (fatal) 二.内存占用分析 1)系统 ...
- itest(爱测试) 开源接口测试,敏捷测试管理平台10.0.0RC1 发布,重点增加压测功能
一:itest work 简介 itest work 开源敏捷测试管理,包含极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock,还有压测 ,又有丰富的统计分析,8合1工作站.可按 ...
- python-一种字符串排序方式
最近工作中,需要使用python实现一种排序方式,简要说明如下: 1.排序方式 假设有一个序列,数据为:['n1', 'n2', 'n10', 'n11', 'n21', 'n3', 'n13', ' ...
- Ansible-playbook剧本进阶
剧本高级特性篇 循环 在写 playbook 的时候发现了很多 task 都要重复引用某个相同的模块,比如一次启动10个服务,或者一次拷贝10个文件,如果按照传统的写法最少要写10次,这样会显得 pl ...