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及其目录结构的更多相关文章

  1. 【VUE】Mac下vue 开发环境搭建,以及目录结构

    1 安装Node.js 参看 node.js环境安装   http://www.cnblogs.com/richerdyoung/p/7265786.html 2 安装淘宝镜像 npm install ...

  2. 【vue iview】项目 win10 放在C盘 经常npm install不成功,就是因为 权限问题,把代码目录放到D盘就没事了。

    [vue iview]项目 win10 放在C盘 经常npm install不成功,就是因为 权限问题,把代码目录放到D盘就没事了.

  3. nodejs npm install全局安装和本地安装的区别

    npm的包安装分为本地安装(local).全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已,比如:代码如下:复制代码npm install # 本地安装npm install - ...

  4. 基于gulp编写的一个简单实用的前端开发环境好了,安装完Gulp后,接下来是你大展身手的时候了,在你自己的电脑上面随便哪个地方建一个目录,打开命令行,然后进入创建好的目录里面,开始撸代码,关于生成的json文件请点击这里https://docs.npmjs.com/files/package.json,打开的速度看你的网速了注意:以下是为了演示 ,我建的一个目录结构,你自己可以根据项目需求自己建目

    自从Node.js出现以来,基于其的前端开发的工具框架也越来越多了,从Grunt到Gulp再到现在很火的WebPack,所有的这些新的东西的出现都极大的解放了我们在前端领域的开发,作为一个在前端领域里 ...

  5. Vue 入门之目录结构介绍

    Vue 是一套用于构建用户界面的渐进式框架,与其它大型的页面框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合.另一方面,当 ...

  6. npm常用命令学习(npm install -D,semver版本规范, npm进行版本管理的最佳实践用法)

    什么是npm npm有两层含义.一层含义是Node的开放式模块登记和管理系统,网址为npmjs.org.另一层含义是Node默认的模块管理器,是一个命令行下的软件,用来安装和管理Node模块. npm ...

  7. vue-cli3安装创建项目以及目录结构

    安装脚手架cli3.0 全局安装 npm install -g @vue/cli 或 yarn global add @vue/cli 查看版本/是否安装成功 vue -V 如果你仍然需要使用旧版本的 ...

  8. React脚手架创建一个React应用以及项目目录结构详解

    react脚手架 用来帮助程序员快速创建一个基于xxx库的模板项目,包含了所有需要的配置,指定好了所有的依赖,可以直接安装/编译/运行一个简单效果 react提供了一个专门用于创建react项目的脚手 ...

  9. React对比Vue(01 数据的定义,使用,组件的写法,目录结构等)

    1.脚手架对比 两个都需要安装node node自带npm 然后安装cnpm yarn(有时候 npm会丢包,所以) npm install -g cnpm --registry=https://re ...

  10. vuejs目录结构启动项目安装nodejs命令,api配置信息思维导图版

    vuejs目录结构启动项目安装nodejs命令,api配置信息思维导图版 vuejs技术交流QQ群:458915921 有兴趣的可以加入 vuejs 目录结构 build build.js check ...

随机推荐

  1. RocketMQ 事件驱动:云时代的事件驱动有啥不同?

    前言: 从初代开源消息队列崛起,到 PC 互联网.移动互联网爆发式发展,再到如今 IoT.云计算.云原生引领了新的技术趋势,消息中间件的发展已经走过了 30 多个年头. 目前,消息中间件在国内许多行业 ...

  2. Java面试题:@PostConstruct、init-method和afterPropertiesSet执行顺序?

    在Spring框架中,@PostConstruct注解.init-method属性.以及afterPropertiesSet()方法通常用于初始化Bean的逻辑.它们都提供了在Bean创建和初始化完成 ...

  3. C语言:如何实现在txt文件中删除超链接、统计单词数量、生成单词列表 (文本流操作并解决乱码)

    1.首先读取原文件内容文本流(包含中英文) 2.删除超链接 3.统计单词数量 4.去除重复单词 读取文件需要自己在文本笔记中保存一个网页,保存为txt文件 注意的是,在这个代码实现过程中,我学到的是如 ...

  4. pageoffice6 版本实现word 文件添加水印

    在很多场景下,Word文档正式发文之前,或者说形成最终文档之前,常常需要往Word文件中添加水印,并且会根据文件类型或内容的不同,需要添加的水印也不一样. 添加水印是Word软件里的一个简单功能,直接 ...

  5. MPI学习笔记(四):矩阵相乘的Cannon卡农算法

    mpi矩阵乘法:C=αAB+βC 一.Cannon卡农算法基本介绍 1.二维矩阵串行乘法 两个n维方阵的乘法A×B=C的串行计算公式为: 下图是用图示来表示的这种计算规则: 2.二维块划分的思想 并行 ...

  6. Swoole 源码分析之 epoll 多路复用模块

    首发原文链接:Swoole 源码分析之 Http Server 模块 大家好,我是码农先森. 引言 在传统的IO模型中,每个IO操作都需要创建一个单独的线程或进程来处理,这样的操作会导致系统资源的大量 ...

  7. 记一次Idea无法打开记录(idea升级)

    记一次Idea无法打开记录 前言,本来今天是打算升级Idea,然后体验一波的,结果升级完之后,发现无法打开idea(双击之后并没有任何打开的反应). 原因排查,打开idea所在目录,找到idea.ba ...

  8. Flutter(五):Flutter 加入现有App的方案选择(Flutter_Boost)

    一.介绍 用 Flutter 一次性重写整个已有的应用是不切实际的.对于这些情况,Flutter 可以作为一个库或模块,集成进现有的应用当中.模块引入到您的 Android 或 iOS 应用(当前支持 ...

  9. PaddleOCR在 Linux下的webAPI部署方案

    很多小伙伴在使用OCR时都希望能过采用API的方式调用,这样就可以跨端跨平台了.本文将介绍一种基于python的PaddleOCR识方案.喜欢的可以关注公众号,获取更多内容. 一. Linux环境下部 ...

  10. 8.10考试总结(NOIP模拟35)[玩游戏·排列·最短路·矩形]

    所谓人,无论是谁到了最后,都会形单影只. T1 玩游戏 解题思路 可以把序列从 k 位置掰成两个序列. 问题就变成了两个序列从开头走向末尾是否可以保证前缀和之和一直不大于 0 . 并且可以移动到两个序 ...