npm i / install
我们都知道npm i 是用来下载依赖包的,并且被下到了node_modules中,那它在这过程中到底发生了什么呢?
在早期的npm处理包采用的就是非常简单粗暴的递归方式了,比如:
假设我们的项目中有一个依赖包pack1,这个pack1又有两个依赖包,分别是p2,p3,p2又有两个依赖包p3和p4,p3也有一个依赖包p2,那么npm就会严格按照这样的结构将依赖包安装到它们各自的node_modules中,一直到子依赖包没有存在其他的依赖包为止。
其实我们也可以看出这样的方式并不是很好,明明项目中只出现了4个依赖包,但是因为这样的结构,就得重复安装之前安装过的依赖包,导致冗余度太高了,并且一个项目的依赖包几乎不会出现只有四个依赖包,如果这个项目非常庞大,依赖的模块也非常多,可想而知,嵌套层级得有多深。
所以npm3版本做了一次比较大的更新,它将嵌套结构改成了扁平结构,扁平结构很好理解,以数组为例,多维数组转成一维数组就是数组扁平化,这里也是一样的,比如上面的依赖树在npm3这里就变成了。
也就是说在安装模块时遇到相同的模块时,会判断已经按照的模块的版本是否和新版本一样,一样就跳过,不一样就在当前模块的node_modules下安装该模块
也就是说如果遇到同一个依赖包,但是依赖版本不同的话怎么办呢?不能一个node_modules中同时出现两个一样的依赖包,那这时候就会按照嵌套关系嵌套了。
举个栗子:
pack1依赖A v1.0.0,pack2依赖A v2.1.0 ,假设pack1的放置位置在pack2前面,那么这时候的依赖树就会变成:
package.json 和package-lock.json
在 npm5x版本中新增了package-lock.json文件,它和package.json有什么区别,它俩的作用又是什么? 先看package.json,我们可以打开它看看里面的代码结构,以下面的为例:
{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "./src/main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^6.7.1",
"style-loader": "^3.3.1",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
}
}
这里我们只提一下devDependencies这个,其他的翻译一下也大致知道。
- devDependencies 大致意思就是开发环境时所用的依赖,还有一个dependencies是生产环境时所用的依赖,这里我们依赖了四个依赖包,也就是说我npm i了这四个包,那么node_modules里就会出现这四个包,那这四个包又会有一大堆依赖,那node_modules一定很大,如果我们把这个项目传到git上,有必要把这个node_modules也打包上去吗?好像没有必要,所以package.json就是对这个项目的一个说明,当别人clone你的项目到本地时,直接npm install就可以把这个项目所要的依赖包下载下来。
那么package-lock.json又有什么作用呢?仔细看package.json里面依赖包的版本号,每个版本号前面都带了一个^这个意思就是向后兼容依赖,也就是说,今年我的项目依赖pack1 1.0.0,明年这个依赖包更新到了1.3.0 那么别人npm install时下载的就是1.3.0版本的依赖包了,简单说package.json只能锁定大版本,也就是版本号的第一位,那么为了解决这类问题,package-lock.json就出来了,它的作用就是锁定小版本,避免出现合作开发时因为版本不同出现的一些问题。