搜索
首页web前端js教程一文聊聊Node包管理发展的五个阶段

从2009年 Node 诞生至今,Node 生态发展繁荣,围绕 Node 生态衍生出的 Node 包管理器百花齐放,先后出现了 npm、kpm、pnpm、yarn、cnpm 等等。实际上 Node 包管理器发展主要分5个阶段,下面我们一起看下每个阶段的关键特征代表产物吧~

阶段一:刀耕火种

正确来说,Node是不存在没有包管理器时期的,2009年,Node.js 问世时 npm的雏形也发布了。【相关教程推荐:nodejs视频教程编程教学

npm 全称 Node.js Package Manager;从A brief history of Node.js 里面可以看到

2009 
Node.js is born 
The first form of npm is created

下面聊一下没有出现Node包管理器时期是怎样的,那时候做的更多的事情就是

  • 网上寻找各软件的官网,比如 jQuery;

  • 找到下载地址,下载 zip 包;

  • 解压,放到项目中一个叫 libs 的目录中;

  • 想更方便的话,直接将 CDN 链接粘贴到 HTML 中

那时候 模块化管理?版本号管理?依赖升级?都不存在的!

阶段二:嵌套安装

2009 年,Node.js 诞生,npm的雏形也正在酝酿,2011年发布了 1.0 版本;npm是围绕着语义版本控制 semver 的思想而设计的,默认认为Node包开发者,在升级依赖包自定义版本号时,都会按照 semver 规范升级版本号。

代名词: Node包管理规范化、node_modules 目录嵌套存放依赖

代表产物: npm v1、v2 版本

关键特点:

(1)依赖包嵌套安装,相同版本的依赖会被冗余安装

(2)依赖包安装不确定性:默认装最新次版本的依赖包(可设置固定版本)

(3)串行安装依赖,速度慢;不支持离线缓存

解释1:依赖 嵌套安装 ,如果A依赖B、B依赖C,node_modules目录如下

node_modules
- package-A
-- node_modules
--- package-B
----- node_modules
------ package-C
-------- some-really-really-really-long-file-name-in-package-c.js

问题: 依赖嵌套过多会造成嵌套地狱,与此同时会出现大量相同依赖包的冗余安装,造成 node_modules 体积过大,需要程序员定期的 rm -rf node_modules,但windows系统,很多程序无法处理超过260个字符的文件路径名,早期 npm 的 windows 用户都见过这个弹窗


解释2:针对每次 npm install 默认安装最新次版本依赖,造成的依赖安装 不确定性 问题:

semver 规范了版本号构成:X.Y.Z-[state],版本号升级规范如下

  • X 是主版本号: API 产生的变化,与旧版本不兼容时,升级主版本号
  • Y 是次版本号: 增加了新的API,但向后兼容,升级次版本号
  • Z 是补丁版本号: 当做了向后兼容的缺陷修复的时候
  • state 可以是:alpha(内测)、beta(公测)、gamma(相当成熟的测试版)、rc(预发布)

版本不确定原因:执行 npm 默认安装依赖指令时,npm 认为开发者都会遵循 semver 版本升级规范,直接给开发者安装 了最新次版本的依赖包

  • 解决方案1:可以通过npm config set save-exact true命令关闭在版本号前面使用 ^的默认行为
  • 总结:无法解决依赖库自己的依赖默认安装最新次版本的问题
  • 解决方案2:npm提供了 shrinkwrap 命令,会生成一个 npm-shrinkwrap.json 文件,为所有库和所有嵌套依赖的库记录精准的版本

  • 总结:锁文件不会默认生成,需要用户手动执行指令;依赖于用户知道这个指令,相对繁琐

阶段三:扁平化安装

2015年,为解决 npm1、npm2 存在的 嵌套安装、版本不规定问题,完全重写了 npm 程序

代名词: 较少冗余依赖的安装、node_modules 目录扁平化存放依赖

代表产物: npm v3版本

原理简述: npm install时,先构建依赖树再将所有依赖都安装在 node_modules 根目录,子依赖遇到不同版本的重名依赖时,会将子依赖安装在自己node_modules下

关键特点:

(1)减少冗余安装:依赖扁平化安装,一定情况下减少了冗余包的安装

存在的问题

(1)“幽灵依赖”、“幻影依赖” 问题

(2)“双胞胎陌生人” 、“依赖包分身” 问题

(3)目录不固定:依赖的安装顺序,决定了 node_module 目录结构

解释1:依赖的依次安装顺序,决定了node_modules 目录结构

如下场景: App1 依赖 packageA 和 packageC 和 packageG 和 packageH,而 packageA 和 packageC 都依赖了 packageB v1.0,packageG、packageH 都依赖 packageB 的 v2.0 版本

如果先安装 packageA 或 packageC,node_modules 目录如下

如果先安装 packageG 或 packageH,node_modules 目录如下

针对如上情况,npm 提供了指令 npm dedupe,可以手动整理&简化 node_modules 的目录结构,整理后的 node_modules 目录结构是一致的,不受依赖包安装顺序影响

解释2:不一定能减少冗余包的安装

通过举例1,可以看出虽然依赖包扁平化安装,但仍存在相同版本的依赖包,有冗余包

解释3:“双胞胎陌生人” 问题

参考举例1中,相同版本的依赖包,被安装两次,被放置到两处,这种现象被称为“双胞胎陌生人”

解释4:“幽灵依赖” 问题

node_modules 一级目录下的依赖包,开发者可以直接使用,但依赖包没定义在 package.json 中,这样的依赖包被称为 “幽灵依赖”,前端项目中使用 “幽灵依赖”,后期可能会出现问题。

因为后期可能伴随着 其他依赖的升级移除了这个“幽灵依赖”,此时 node_modules 中就不存在了,执行 npm install 时,并不会主观的去安装 “幽灵依赖”,导致项目找不到依赖包,然后报错。

阶段四:安全、提速

2016年,yarn、pnpm release 版本相继出现,在一定程度上解决了之前的 安装版本不确定、安装速度慢等问题,yarn 率先推出的能力相比于 npm,更夺人眼球,保证了一致性&安全性,提升了安装速度

代名词: 依赖安装相对安全、提速

代表产物: yarn release版本、pnpm release版本、npm v5 版本(npm v4没有太大变化,v5向前迈了一大步)

关键特点:

(1)安全:默认生成版本锁文件,保证了每次安装依赖版本都一样

(2)提速:增加了缓存离线安装、并行安装、安装异常后自动重试

(3)workspace:yarn从v1版本开始支持,可以高效管理多个项目的依赖包;npm v7才支持 workspace

存在的问题

(1)幽灵依赖

(2)依赖包单项目重复安装、跨项目重复安装

(3)目录不固定:依赖的安装顺序,决定了 node_module 目录结构

解释1:关于安全

yarn v0.x 版本率先、npm v5.x 版本紧跟其后,下载依赖时,默认生成 依赖锁文件,精确地将版本锁定在一个值

  • yarn 的 .lock 文件:只是记录安装的依赖版本,需要结合 package.json 来确定 node_modules 目录结构
  • npm 的 .lock 文件:记录了安装的依赖版本 及 node_modules 目录结构

总结: 避免了不同终端安装依赖时版本不一致问题,但“依赖幽灵” 问题仍然存在

解释2:关于提速 - 离线缓存

npm v2版本 就支持了缓存,但需要联网检测,才能使用 缓存的依赖

yarn v0.x版本 率先支持了 离线缓存,从网络下载的包都会缓存到全局,下次安装优先从本地找,找到直接copy

npm v5版本 重写了缓存系统,也支持了离线安装,安装速度大大提升

解释3:关于提速 - 并行安装

yarn 率先支持了依赖包并行安装,此前 npm 串行安装依赖,后来 npm 也优化了并行安装

解释4:安装依赖后,自动整理 node_modules 目录

起始时间:yarn v1.x 版本、npm v4.x 版本

  • 如果项目中删除了 .lock 文件,初始化安装依赖时,会自动整理 node_modules 目录;npm v4.x之前版本,需要用户手动执行指令 npm dedupe整理依赖目录
  • 由于 node_modules 是扁平化管理依赖,深层依赖可能会被安装到一级目录下;当项目中再安装不同版本的依赖时,遇到依赖版本冲突,会自动将深层依赖从一级目录移动到父依赖目录下 【已验证】

阶段五:更安全、高速、低耗

对着 pnpm 的成熟,开发者们享受着 pnpm 带来的 更安全、更高速、存储更低耗 等红利,解决了“幽灵依赖” 问题,解决了重复依赖问题

代名词: 安全(依赖安装所见即所得)、高速(不重复安装)、存储低耗(硬链接 + 软链接)

代表产物: pnpm

关键特点:

(1)速度极快:存储中心集中管理依赖,直接硬链接到项目的 node_modules/.pnpm 中。相比于之前的工作方式,减少了从全局 node_modules copy 到项目内的大量 IO 操作

(2)磁盘利用率极高

  • 跨项目共用相同版本的依赖:硬链接、软链接
  • 最大限度的复用同一依赖的不同版本:只增加存储不同版本的 Diff 文件

(3)安全性高:node_modules 目录结构就是 package.json 依赖列表,解决了 “幽灵依赖” 问题

性能表现如下:

更多node相关知识,请访问:nodejs 教程

以上是一文聊聊Node包管理发展的五个阶段的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:掘金社区。如有侵权,请联系admin@php.cn删除
Python vs. JavaScript:开发人员的比较分析Python vs. JavaScript:开发人员的比较分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

Python vs. JavaScript:选择合适的工具Python vs. JavaScript:选择合适的工具May 08, 2025 am 12:10 AM

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript:了解每个的优势Python和JavaScript:了解每个的优势May 06, 2025 am 12:15 AM

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

JavaScript的核心:它是在C还是C上构建的?JavaScript的核心:它是在C还是C上构建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript应用程序:从前端到后端JavaScript应用程序:从前端到后端May 04, 2025 am 12:12 AM

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架:为现代网络开发提供动力JavaScript框架:为现代网络开发提供动力May 02, 2025 am 12:04 AM

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

JavaScript,C和浏览器之间的关系JavaScript,C和浏览器之间的关系May 01, 2025 am 12:06 AM

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器