npm、cnpm、yarn、pnpm区别以及pnpm 是凭什么对 npm 和 yarn 降维打击的

2023-11-17

安装

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的这种平铺方式确实是解决了层级依赖深和包的利用率的问题,但是也引入了其他的问题:

  1. 对没有手动引入的包,例如express@4.18.1依赖的cookie,项目中手动引入,但是依然可以使用,这样就造成了如果哪天express改变了策略不在使用cookie,而我们的项目中又使用了cookie,这样就会导致项目无法启动
  2. 虽然npm是共享了相同版本的依赖,但是如果版本不同,npm还是会完整的下载两个不同的版本,这样也会有依赖的冗余
  3. 幽灵依赖的问题: 由于npm(v3+)、yarn等包管理工具会将安装的node_module包进行扁平化结构的处理,即将所有依赖与其的依赖展开在一个层级,即根目录,这样就使得在代码中你不仅可以引用package.json中的依赖,也可以引用其所依赖的部分。
pnpm的依赖

创建非扁平化的node_module文件夹

  1. 在pnpm创建非扁平化的结构过程中,这里出现了两种箭头指示:

    Hard Link
    Symbolic Link
    什么是Hard Link?
    字面意思:硬链接

    hard link 使得用户可以通过不同的路径引用方式去找到某个文件

    可以看官方文档中的图片,链接指向的都是.pnpm store

    pnpm在这里存放了所有依赖的Hard Links,每个依赖可以理解为只存在一份,且在store中。

  2. 什么是Symbolic Link?
    字面意思:符号链接

可以看作为我们常规操作的快捷方式,当其他依赖需要相同依赖的时候,采用符号链接而不需重新下载。详细的看访问官网查看https://pnpm.io/zh/motivation

在这里插入图片描述
官方给的一些对比
详细访问改地址https://pnpm.io/zh/feature-comparison
在这里插入图片描述

pnpm的使用

项目初衷

节省磁盘空间

在这里插入图片描述
使用 npm 时,依赖每次被不同的项目使用,都会重复安装一次。 而在使用 pnpm 时,依赖会被存储在内容可寻址的存储中,所以:

  1. 如果你用到了某依赖项的不同版本,只会将不同版本间有差异的文件添加到仓库。 例如,如果某个包有100个文件,而它的新版本只改变了其中1个文件。那么 pnpm update 时只会向存储中心额外添加1个新文件,而不会因为仅仅一个文件的改变复制整新版本包的内容。
  2. 所有文件都会存储在硬盘上的某一位置。 当软件包被被安装时,包里的文件会硬链接到这一位置,而不会占用额外的磁盘空间。 这允许你跨项目地共享同一版本的依赖。
    因此,您在磁盘上节省了大量空间,这与项目和依赖项的数量成正比,并且安装速度要快得多!
提高安装速度

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 降维打击的

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

npm、cnpm、yarn、pnpm区别以及pnpm 是凭什么对 npm 和 yarn 降维打击的 的相关文章

随机推荐

  • LeetCode:动态规划中的子序列问题

    PS 本文是参考代码随想录做的一些笔记 完整版本请戳链接 非常好的教程 本文列举了一些经典题目 特别是编辑距离 基本上的题目解题思路都是一样的 可以说是一个路子 300 最长递增子序列 给你一个整数数组 nums 找到其中最长严格递增子序列
  • 基础学习----对于我来说一些基础引脚知识

    1 BOOT BOOT 引脚可以配置为不同的状态 以决定芯片在启动时从哪个存储器中加载程序或固件 具体来说 BOOT 引脚有两个状态 BOOT0 这是一个普通输入 输出引脚 用于配置芯片的启动模式 当 BOOT0 引脚为低电平时 芯片将从
  • 从Dialog管理谈到Vue渲染原理

    作为一个中后台表单 表格工程师 经常需要在一个页面中处理多个弹窗 我自己的项目中 一个复杂的审核页面中的弹窗数量超过了30个 如何管理大量的弹窗就成为了一个需要考虑的问题 大量的弹窗有什么问题 假设你有一个弹窗组件 类似于element u
  • 玩以太坊链上项目的必备技能(类型-引用类型-Solidity之旅三)

    在前文我们讲述了值类型 也就说再修改值类型的时候 每次都有一个独立的副本 如 string 类型的状态变量 其值是无法修改 而是拷贝出一份该状态的变量 将新值存起来 对于处理稍微复杂地值类型时 拷贝将变得愈发大了 也正是介于此 才考虑到将数
  • 数据库错误Warning in ./libraries/config/FormDisplay.php#661

    宝塔面板的phpMyAdmin目录为 www server phpmyadmin 然后搜索 FormDisplay php 在661行将continue改为break 保存 关闭 重新打开phpMyAdmin 宝塔面板 数据库 管理 ok
  • 编译报错error while loading shared libraries找不到libsigsegv.so.2解决思路

    笔者在Ubuntu交叉编译openwrt系统时 遇到了错误error while loading shared libraries 提示找不到libsigsegv so 2这个库 而且是makefile在执行awk这个指令时报的错 分析过程
  • Mybatisplus使用easycode

    在插件栏里下载easycode 然后在如下路径找到easycode配置 设置实体类的模板 因为自带的模板并不适合我们直接的开发 导入宏定义 define vm 保存文件 宏定义 save entity java 包路径 宏定义 setPac
  • 嵌入式原理图入门-UART

    串口 UART Universal Asynchronous Receiver Transmitter 即通用异步收发传输器 简称串口 抓取日志 还有很多的外设也是用串口进行通讯 例如GPS模块 蓝牙模块 电表 锁板等 串口硬件及原理图 串
  • SpringBoot获取Request的3种方法!

    HttpServletRequest 简称 Request 它是一个 Servlet API 提供的对象 用于获取客户端发起的 HTTP 请求信息 例如 获取请求参数 获取请求头 获取 Session 会话信息 获取请求的 IP 地址等信息
  • Linux SATA驱动

    驱动层次关系 0 gt sata xxx c sata的平台驱动 1 gt drivers of xxx c 设备树相关操作 of xxx 1 gt sata xxx c 不同芯片自己的init irq handler ata port o
  • android webdav 播放器,Android APP 推荐:WebDAV Server(不借助数据线在电脑和手机间同步数据)...

    很久以前就在知乎上看过这样的一个问题 Android 手机和电脑之间共享数据 同步数据 不通过数据线连接 有什么好的解决方案 虽然回答挺多的 但是没有一个是我比较满意的 后来也了解到一些软件 宣称可以很少的实现同步电脑和手机的数据的功能 例
  • Linux VI与文件查看命令

    vi 进入linux系统的交互式编辑器 VI模式转换 i 插入模式 lt gt 命令行模式 lt gt 底行模式 esc esc 命令行模式常用命令 0 移到当前行的最前 移到当前行的最后 H 移到屏幕第一行 L 移到屏幕末行 gg 移到文
  • 蓝桥杯模拟赛第一期 充电器C语言

    问题描述 小蓝有一个充电器 可以使用不同的电压和电流充电 给定充电器工作的记录 请计算在这个记录期间总共通过充电传输了多少电能 输入格式 输入第一行包含一个整数 n 表示记录的条数 接下来 n 行 每行包含一个时刻 T 和两个非负整数 U
  • Unity资源常用目录和路径大总结

    一 资源路径 Unity中的资源路径在Window平台下打印出来如下图 Android平台 iOS平台 二 Unity3D中的资源访问介绍 1 Resources 是Unity3D系统指定文件夹 如果你新建的文件夹的名字叫Resources
  • AI算法工程师岗位职责解析

    岗位职责 1 深度学习算法研究 实现和优化 负责特定需求的深度学习算法解决方案 2 负责针对业务问题场景 设计和实现具体应用的深度学习模型 策略 算法 改进业务 3 研究文本 图片 视频等多种内容数据的语义理解的算法和技术 跟进业界深度学习
  • 数据分析规范总结-V2.0

    结构规范及写作 报告常用结构 1 架构清晰 主次分明 数据分析报告要有一个清晰的架构 层次分明能降低阅读成本 有助于信息的传达 虽然不同类型的分析报告有其适用的呈现方式 但总的来说作为议论文的一种 大部分的分析报告还是适用总 分 总 的结构
  • MySQL数据库(三)SQL之DDL、DML语句

    成功不易 加倍努力 1 DDL语句 1 1 创建表 1 2 表查看 1 3 修改和删除表 2 DML语句 2 1 INSERT 语句 2 2 UPDATE 语句 2 3 DELETE语句 1 DDL语句 表 二维关系 设计表 遵循规范 定义
  • OS中 main.h 的一些基本概念 以及 类与对象的概念及其实现

    目录 头文件 import lt gt 与 import 的区别 include 与 import 的区别 OC语言的特点 自动释放池 面向对象的 特征 与 概念 以及其基本思想 类 与 对象 的概念 如何用OC中创建与使用对象 如何给对象
  • 力扣每日一题——上升下降字符串

    题目链接 class Solution public string sortString string s int len s length 获取字符串长度 char ch 501 创建字符串数组 string sh 创建结果字符串 boo
  • npm、cnpm、yarn、pnpm区别以及pnpm 是凭什么对 npm 和 yarn 降维打击的

    安装 1 安装npm需要安装nodejs node中自带npm包管理器 node下载地址 node js 2 cnpm安装 需要安装npm cnpm是淘宝团队做的npm镜像 淘宝镜像每 10分钟 进行一次同步以保证尽量与官方服务同步 npm