在网友疯狂吹捧pnpm牛逼的氛围中,逐步了解了npm历史以及它的短板. 反之也是pnpm的优势之一减少依赖包的反复安装. 其实现的基础是因为计算机底层的文件系统支持软链和硬链. 顺带整理一下.
随便进入到一个文件夹内,输入以下命令查看文件的详细信息:
bash
ls -li
第一项这一串数字叫做索引节点(inode) ,在文件系统中,保存在磁盘分区中的文件,不管是什么类型,系统都会给他分配一个编号它是该文件或者目录在系统中的唯一标识.
硬链接
创建硬链接对应操作系统的命令是:
go
// ln <target> <hardlink>
ln package.json package.hard.json
可以看到生成的package.hard.json
文件的inode(130833506)没有变且文件类型等元数据都跟package.json
相同,这种方式创建的package.hard.json
就是硬链接.
特点:
- 两个文件的inode信息相同,其他信息也完全相同
- 每多一个文件指向改inode,链接数就会+1。当值减到 0,系统就自动回收 inode 及其对应的 block 区域
与源文件的关系:
软链接
同样创建软链接加上-s (soft)参数就行:
go
ln -s package.json package.symlink.json
可以看到创建的package.symlink.json
有不同的inode,因为内部只存储了一个链接信息所以文件大小也相对较小!
特点:
- 软链接和源文件是不同的inode,其他信息也不同
- 软链接文件只是存储了一个链接信息,所以文件size很小
与源文件的关系:
总结
软链接和硬链接通过不同的方式来减少磁盘空间 (都可减少磁盘空间占用),可以使用du -sh
命令查看文件夹总大小,系统右键查看文件总大小不可靠.
软链接 | 硬链接 | |
---|---|---|
inode | 软链接与源文件拥有不同的inode,是两个不同的文件 | 硬链接和源文件拥有同一个inode,它们其实互为硬链接 |
文件属性 | 链接文件 | 与源文件类型相同 |
跨文件系统建立 | 支持 | 不支持 |
链接数目 (也就是文件信息中的nlink) | nlink不会随着软链接数目增加 | 每增加一个两链接nlink也会加1 |
删除源文件 | 软链接无法正常访问 | 硬链接文件可正常访问 |
应用 | 1. pnpm中解决幻影依赖的场景2. 快捷方式 3.文件替身 | 文件备份防误删 |
前端应用
npm/yarn link: 软链接的使用
pnpm: 硬链接、软链接都用
npm link原理
创建一个空目录,该目录下有两个项目,projectA和projectB, projectB中导出一个方法:
接下来我希望pA能使用pB导出的方法,由于Node.js 不支持直接从目录中导入 ES 模块.
所以除了将pB发布成npm包之外,另外的方法就是pA link pB.
link成功之后可以在pA的node_modules中看到pB(右侧有一个软链接的符号)
ok,整体感官上就是这样,现在我想知道在pB中执行npm link
,和pA中执行npm link projectb
分别做了什么事情.
pB中执行npm link
首先我们查找一下npm 全局的安装位置 which npm
,mac 一般会安装在/usr/local/lib/node_modules目录下.
可以发现全局node_modules下多了一个projectb, 根据上边软链接的特点,了解到projectb
其实是一个软链接文件(lrwxr-xr-x中的l即表示软链接),真实的源文件是后边那个,也就是我执行npm link时的目录.所以:
- 在pB中执行
npm link
时,会在全局的node_modules中创建一个pB的软链接文件
pA中执行npm link projectb
会在pA的node_modules中创建名称为projectb的软链接文件
链接指向全局node_modules/projectb
所以:
- 在pA中执行
npm link projectb
时,会在pA/node_modules下创建一个软链接文件,它指向的是全局的软链接文件,而非pB源文件
记住几个目录,在查看软链指向的时候会疯狂使用到:
全局: /usr/local/lib/node_modules
项目内: pA/node_modules
问题
Q1: 如果不使用link,直接在pA/node_modules下手动创建一个名为pB的软链接文件,代码能正常运行吗?
A:是的,link原理就是这样,但需要注意手动创建软链接时,目录尽量使用绝对路径!
参考: