前端现代包管理器的进化史

北京痤疮医院那个好 http://pf.39.net/bdfyy/zjft/210630/9125685.html

字节跳动巨量星图/TCM团队持续招聘前端工程师,详情可见文后/字节跳动巨量星图/TCM团队招聘前端工程师

现在很多项目都会使用pnpm替代npmoryarn来做包管理,众所周知pnpm的宣传里有一个很吸引人的点是可以更小更快的安装我们的依赖。那么

为什么pnpm能做到更小更快呢?除了更小更快他还解决了哪些问题让大家得以青睐呢?

要回答这些问题,就得了解这些年包管理的几场重大”变革“,于是便有了今天的分享。

Npmv1v2

刚开始npm的设计非常的简单:有一个标准的包管理器供大家下载和查阅,将开发人员从那个“网上下载资源,在手动解压添加近项目”的年代中解放出来。所以初版npm使用了很简单嵌套结构来进行版本管理。

我们假设有这样两个项目:

App1依赖packageA和packageC,而packageA和packageC都依赖了packageB;App2依赖packageB和packageD,packageD依赖packageE,packageE依赖packageF......

那么这两个项目的nodule_packages目录结构如下:

这样做带来的问题也显而易见:

项目里会反复安装相同的依赖:比如App1下重复安装了packageB会带来依赖地狱:比如App2下的D,E,F......不同的项目之间会重复安装相同的包:比如App1和APP2都安装了packageB

网上为此有一些经典的梗:

Npmv3

为了解决上述的问题,npmv3完全重写了npm的安装程序,采用扁平化的方式,将主依赖项和子依赖都装到node_modules一级目录下,还是上面那个例子,此刻node_modules的目录结构如下:

这时项目内的重复安装和依赖地狱看似都得到了不错的解决,但此刻又带来了一些新的问题:

1.不完全解决的重复依赖

我们假设App1又有了新的依赖packageG和packageH,packageG、packageH都依赖packageB的v2.0版本,那么此刻node_modules的依赖可能是以下结构:

由于A、C和G、H依赖的是不同版本的B,所以子依赖项提升时只会提升v1.0版本的packageB,v2.0版本的packageB依旧挂在G,H下。显而易见,G和H依旧安装了两份同样的packageBv2.0。

2.不确定性

发现我上述说:“node_modules的依赖可能是以下结构”,因为node_modules的结构还可能是下面这种:

这个例子里packageBv2.0得到了提升,A和C下挂着Bv1.0。

那么到底是提升Bv1.0还是提升Bv2.0?取决于用户的安装顺序(install操作),这种不确定性为项目的依赖问题解决带来了极大的困难,不同的成员install的结果不一定是一样的......

3.隐式依赖(又名幽灵依赖)

在上述的例子里,虽然App1没有直接声明引用packageB,但项目里依旧可以正常的使用。原因是npm3将所有的依赖都平铺到node_modules下,因此require函数可以查找到它,这样也给项目带来了一些风险:

阅读困难:没有在package.json里定义却可以引入这个包,why???引入的版本不确定性:像上面这个例子,App1require的packageB是v1.0版本还是v2.0版本完全取决于ACGH的依赖,如果有一天ACGH版本更新依赖packageBv5.0版本了,App1在不知情的情况下依赖的版本从v1.0升级到v5.0,或许会给项目带来意想不到的问题。Yarn

年,Facebook在


转载请注明:http://www.aierlanlan.com/cyrz/355.html