pnpm学习笔记

传统的包管理工具劣势

  • 当使用npm或Yarn或者cnpm时,如果有100个项目,并且所有项目都有一个相同的依赖包,那么,在硬盘上就需要保存100份该相同依赖包的副本,这些副本互为拷贝,修改各自项目三方包的源码不会相互影响(但是为什么要修改三方包的源码呢?没必要);如果依赖过多,会导致项目较大,当本地存储的项目较多时,对于磁盘存在一定的压力。
  • 传统的包管理工具创建的node_modules目录是扁平化的,即:所有三方包的依赖都被提升到node_modules根目录下(例如,webpack也依赖其他包,这些依赖会被提升到整个项目的node_modules文件夹下);
    • 结果是:源码可以访问本不属于当前项目所设定的依赖包(项目的package.json)

硬链接&&软链接

  • 硬链接(hard link):
    • 是电脑文件系统中的多个文件平等地共享同一个文件存储单元;
    • 删除一个文件名字后,还可以用其它名字继续访问该文件;
    • 硬链接不能操作目录,只能操作文件。
1
2
3
4
5
6
7
8
window:
mklink /H 新建的硬链接文件名 源文件名
macOS:
ln 源文件 新建的硬链接文件

例如:
mklink /H test.js test_hard.js
test.js为原文件,创建一个test.js的硬链接文件test_hard.js,修改任意一个文件的内容,另一个文件也会被修改。

硬链接图示:

硬链接图示

  • 软链接(soft link、Symbolic link):>可理解为快捷方式>
    • 符号链接是一类特殊的文件;
    • 其包含有一条以绝对路径或者相对路径的形式指向其它文件或者目录的引用;
1
2
3
4
window: 
mklink 新建的软连接文件名 源文件名
macos:
ln -s 源文件名 新建的软连接文件名

软链接图示:

软链接图示

软链接图示

软硬链接图示:

软硬链接图示

说明:如果源文件被删除,使用软连接创建的文件(名)将不能够访问磁盘的真实文件;硬链接创建的文件(名)仍然能够访问。

即上图中,软连接删除了OriginalFile,softLink的引用将断开;硬链接删除OriginalFile,使用HardLink仍然能够访问磁盘的真实文件。

pnpm

pnpm:performant npm (高性能的包管理器)

优势

pnpm相较于传统的包管理工具的优势:

  1. 如果你对同一依赖包使用相同的版本,那么磁盘上只有这个依赖包的一份文件;

    如果你对同一依赖包需要使用不同的版本,则仅有版本之间不同的文件会被存储起来;

    所有文件都保存在硬盘上的统一的位置:

    • 当安装软件包时,其包含的所有文件都会硬链接到此位置,而不会占用额外的硬盘空间;

    • 这让你可以在项目之间方便地共享相同版本的依赖包;

  2. pnpm采用非扁平化的安装方式:

    • 带来另外一个问题:多以包依赖同一个包,这个包会被安装多次,但是pnpm也考虑到了这个问题。

目录结构:

某个项目依赖axios,在使用pnpm管理依赖的前提下,node_modules的目录结构为:

node_modules的目录结构

说明:

  • 项目的node_modules文件夹下,仅有axios依赖(本项目仅仅依赖axios库,就避免了使用commonjs或者esmodule引入依赖时,不可以访问本不属于当前项目所设定的依赖包);
  • node_modules的axios属于软链接,真正的文件位于.pnpm文件夹下,在.pnpm之下,有一个axios@0.27.2文件,其下有一个node_modules文件夹,包含了自身的源码(硬链接)以及axios所需要的其他依赖的软链接;
  • axios@0.27.2/node_modules目录之下,有axios的其他依赖软链接,其中,form-data的目录结构和axios@0.27.2/node_modules类似

pnpm的存储store

  • 在pnpm7.0之前,统一的存储位置是~/.pnpm-score中的;

  • 在pnpm7.0之后,统一的存储位置进行了更改: <pnpm home directory> /store

    • 在Linux上,默认是~/.local/share/pnpm/store

    • 在 Windows 上: %LOCALAPPDATA%/pnpm/store

    • 在macOS 上: ~/Library/pnpm/store

    • 也可以使用pnpm的命令

    1
    2
    pnpm store path
    // 在不同的目录使用pnpm store path命令,结果可能不同,这是因为不同的磁盘之间不能创建相关的硬链接(比如固态和机械,不同的磁盘之间)

windows下的存储目录

window下全局pnpm依赖所在的store

pnpm的store存储了当前操作系统所有依赖的硬链接,在有新项目存在相同的依赖时,pnpm会根据store存储的相关信息,根据相关算法对新项目的依赖创建硬链接

pnpm的裁剪

pnpm的存储方式带来了另外一个问题:

所有的项目的依赖的所有文件在.pnpm-store都存在一份硬链接,随着创建的项目越来越多,或者本地项目的删除,同时随着依赖的逐渐升级,早期版本的依赖已经不再使用,但是这些文件的硬链接仍然存在,会导致.pnpm-store越来越大,虽然相较于传统的npm等工具,其占用的空间大大减少,但是对于磁盘仍然会有一定的存储压力(虽然情况已经好很多了)。

1
2
pnpm store prune
// 从store中删除当前未被引用的包来释放store的空间