安装
1、安装npm需要安装nodejs,node中自带npm包管理器
node下载地址:node.js
2、cnpm安装(需要安装npm)
cnpm是淘宝团队做的npm镜像,淘宝镜像每 10分钟 进行一次同步以保证尽量与官方服务同步。
npm install -g cnpm --registry=https://registry.npm.taobao.org
3、yarn安装(需要安装npm)
npm install -g yarn
官网地址:安装 | Yarn 中文文档
4、pnpm安装(需要安装npm)
npm install -g pnpm
官网地址: pnpm 中文文档
npm和yarn的比较
1、并行安装:yarn安装包会同时执行多个任务,npm 需等待上一个任务安装完成才能运行下一个任务(按照在package.json中声明的顺序),所以npm install 下载速度慢,即使是重新 install 时速度依旧慢
2、离线模式:如果你已经安装过一个包,用 yarn 再次安装会从缓存中获取,而 npm 会从网络下载
3、版本锁定:yarn 默认有一个 yarn.lock 文件锁定版本,保证环境统一,npm是通过
package-lock.json
4、更简洁的输出:yarn 安装包时输出的信息较少,npm 输出信息冗余
5、常用指令对比:
npm和yarn同时混用会有什么问题
当我们运行npm i lodash --save,lodash将会被当做依赖加入到package.json中:
"dependencies": {
"loadsh": "^4.17.4"
}
package.json文件版本符号的特点
由于package.json文件中的版本号的特点,下面的三个版本号在安装的时候就代表不同的含义。
"6.0.3"表示安装指定6.0.3版本,
"~6.0.3"表示安装6.0.X中最新的版本,
"^6.0.3"表示安装6.X.X中最新的版本,
举个例子:以typescript依赖包为例
1、原项目中使用package.json定义项目中需要依赖的包,这里的typescript版本号为^4.2.4
2、原项目是用npm来进行包管理,从而生成package-lock.json文件,里面存储了各个依赖的具体来源和版本号,其中typescript的版本号为4.2.4,所以今后使用npm进行安装依赖时都会安装typescript的4.2.4版本,不会进行自动升级
3、如开发者使用yarn命令来进行包依赖安装,则package-lock.json文件无效,只看package.json中的文件,但typescript版本号为^4.2.4,从而会安装4.x.x版本中最新版本即为4.6.3版本,同时生成对应yarn.lock文件
4、启动项目会出现typescript类型报错,其原因是因为原项目是在4.2.4typescript版本环境下编写,但使用yarn进行依赖安装把typescript版本自动更新成了 4.6.3版本,同时4.2.4和4.6.3版本的typescript在类型校验上进行了较大的改进和优化,可以检测出更多的类型问题
所以,如有yarn.lock文件而没有package-lock.json文件则项目是以yarn 来进行包管理;
如有package-lock.json文件而没有yarn.lock文件则项目是以npm来进行包管理。
关于版本也可以参考这篇文章 https://blog.csdn.net/big_wolf0/article/details/124294655
为什么说pnpm是最先进的包管理工具
1、在npm3以前,采用的是嵌套安装的方式。假如我们安装依赖B和C时,如果B和C依赖中依赖了 packageD,那么会将 packageD重复安装2次。这将导致 会占据比较大的磁盘空间,且 windows 的文件路径最长是 260 多个字符,这样嵌套是会超过 windows 路径的长度限制的。
2、npm3+和yarn采取铺平的方式,将依赖扁平化,所有的依赖不再一层层嵌套了,而是全部在同一层,这样也就没有依赖重复多次的问题了,也就没有路径过长的问题了。
npm2的依赖管理
npm2生成的依赖管理比较的简单直接,会按照安装包的依赖树形结构直接填充在本地的目录结构下:
比如express和koa他们会同时依赖accepts,那么在install之后生成的node_modules就会是如下结构
npm2的这种方式的优点就是比较的直观,但是呢缺点也是显而易见的就是
层级依赖过深
相同包的相同版本会多次被下载,利用率低,占用磁盘空间大
npm3/yarn的依赖管理
针对npm2的两个缺点呢,npm3做了个改变,不再使用嵌套的结构了,而是讲依赖进行打平,这样就能解决层级依赖深和包的利用率的问题,那么上面的依赖关系就会变成下面这个样子:
我们可以看出,express@4.18.1和koa@2.13.4引用了accepts的版本是一样的,这样才会被平铺在node_modules下,那如果引用的包的版本不一样又是什么样的情况呢?就像debug,http-errors 、statuses等这几个包
express@4.18.1引入的是:debug@2.6.9、http-errors@2.0.0、statuses@2.0.1
koa@2.13.4引入的是:debug@4.3.2、http-errors@1.6.3、statuses@1.5.0
此时,在node_modules结构是下面这个样子
npm3的这种平铺方式确实是解决了层级依赖深和包的利用率的问题,但是也引入了其他的问题:
- 对没有手动引入的包,例如express@4.18.1依赖的cookie,项目中手动引入,但是依然可以使用,这样就造成了如果哪天express改变了策略不在使用cookie,而我们的项目中又使用了cookie,这样就会导致项目无法启动
- 虽然npm是共享了相同版本的依赖,但是如果版本不同,npm还是会完整的下载两个不同的版本,这样也会有依赖的冗余
- 幽灵依赖的问题: 由于npm(v3+)、yarn等包管理工具会将安装的node_module包进行扁平化结构的处理,即将所有依赖与其的依赖展开在一个层级,即根目录,这样就使得在代码中你不仅可以引用package.json中的依赖,也可以引用其所依赖的部分。
pnpm的依赖
创建非扁平化的node_module文件夹
-
在pnpm创建非扁平化的结构过程中,这里出现了两种箭头指示:
Hard Link
Symbolic Link
什么是Hard Link?
字面意思:硬链接hard link 使得用户可以通过不同的路径引用方式去找到某个文件
可以看官方文档中的图片,链接指向的都是.pnpm store
pnpm在这里存放了所有依赖的Hard Links,每个依赖可以理解为只存在一份,且在store中。
-
什么是Symbolic Link?
字面意思:符号链接
可以看作为我们常规操作的快捷方式,当其他依赖需要相同依赖的时候,采用符号链接而不需重新下载。详细的看访问官网查看https://pnpm.io/zh/motivation
官方给的一些对比
详细访问改地址https://pnpm.io/zh/feature-comparison
pnpm的使用
项目初衷
节省磁盘空间
使用 npm 时,依赖每次被不同的项目使用,都会重复安装一次。 而在使用 pnpm 时,依赖会被存储在内容可寻址的存储中,所以:
- 如果你用到了某依赖项的不同版本,只会将不同版本间有差异的文件添加到仓库。 例如,如果某个包有100个文件,而它的新版本只改变了其中1个文件。那么 pnpm update 时只会向存储中心额外添加1个新文件,而不会因为仅仅一个文件的改变复制整新版本包的内容。
- 所有文件都会存储在硬盘上的某一位置。 当软件包被被安装时,包里的文件会硬链接到这一位置,而不会占用额外的磁盘空间。 这允许你跨项目地共享同一版本的依赖。
因此,您在磁盘上节省了大量空间,这与项目和依赖项的数量成正比,并且安装速度要快得多!
提高安装速度
pnpm 分三个阶段执行安装:
- 依赖解析。 仓库中没有的依赖都被识别并获取到仓库。
- 目录结构计算。 node_modules 目录结构是根据依赖计算出来的。
- 链接依赖项。 所有以前安装过的依赖项都会直接从仓库中获取并链接到 node_modules。
这种方法比传统的三阶段安装过程(解析、获取和将所有依赖项写入node_modules)快得多。
创建一个非扁平的 node_modules 目录
使用 npm 或 Yarn Classic 安装依赖项时,所有的包都被提升到模块目录的根目录。 这样就导致了一个问题,源码可以直接访问和修改依赖,而不是作为只读的项目依赖。
默认情况下,pnpm 使用符号链接将项目的直接依赖项添加到模块目录的根目录中。
更详细的可以查看官网https://pnpm.io/zh/cli/env
这里主要说以上两个命名
pnpm dlx
从源中获取包而不将其安装为依赖项,热加载,并运行它公开的任何默认命令二进制文件。
pnpm env
管理 Node.js 环境。
使用
安装并使用指定版本的 Node.js
安装 LTS 版本的 Node.js:
pnpm env use --global lts
安装 v16 的Node.js
pnpm env use --global 16
安装 Node.js 的预发行版本
pnpm env use --global nightly
pnpm env use --global rc
pnpm env use --global 16.0.0-rc.0
pnpm env use --global rc/14
安装最新版本的 Node.js:
pnpm env use --global latest
使用 codename 安装 Node.js 的 LTS 版本:
pnpm env use --global argon
remove, rm
移除指定版本的 Node.JS.
用法示例:
pnpm env remove --global 14.0.0
list, ls
列出本地或远程可用的 Node.js 版本。
输出本地安装的版本:
pnpm env list
输出远程可用的 Node.js 版本:
pnpm env list --remote
输出远程可用的 Node.js 16 版本:
pnpm env list --remote 16
pnpm 是凭什么对 npm 和 yarn 降维打击的