一:什么是包管理工具.
前端项目会通过node下载一些依赖,来辅助我们实现和优化项目. 对于这些依赖的管理,就是 前端的工程化管理. 这些都是 node-module 在管理,那么管理工具有什么呢?npm,cnpm,yarn,pnpm都是.(对依赖的下载,更新,删除)
二.node-module的对依赖的管理
对于任意一个文件夹,我们npm init 初始化之后,他都会有一个package.json.里面记录了有哪些依赖.我们打开 node-module.里面的依赖文件夹,也会有这些东西.我们的依赖,也会有它自己的依赖.所以我们的文件夹,都会有一个叫 依赖树 的东西.表示所需要的依赖,和这些依赖之间的关系.
例如: A 有B C 2个依赖,2个依赖都又依赖了D. 按照这个模式,每一个依赖都会生成一个nodemodule来存储依赖.我们就存了2个D. 这就浪费磁盘空间了.
2015年以前,npm都是通过以上的方式来存储依赖,但是为了解决这个问题.他后面,采用了扁平化的方式来存储依赖.不管谁依赖了谁(ABCD).这些依赖在node_module里面,都是同级存储.
三.幽灵依赖
因为所有的依赖都被扁平了.我packagejson里面写了安装A,A依赖B.那么B也会被扁平得安装在文件夹里面. 那么我们就可以直接引用B.因为我们能直接在依赖文件夹里面找到B. 这个时候,可能发生以下情况: A. 我们手动得删除了A文件夹.这个时候,我们项目不会报错,但是在别人得电脑上,或者是生产环境.他们通过package文件,没有安装A依赖,也就不会安装B,所以他们会报错.
B. 我们直接通过npm uninstall 卸载了A依赖,B也会被卸载(如果没有其他的依赖CDE...依赖B,或者package里面项目直接依赖).我们得项目也会直接报错
C. 我们通过npm,对A进行了版本升级,此时B也许会被A同步同级.我们之前直接依赖B,这个时候,版本不一样,可能就会出问题了.
pnpm
pnpm解决幽灵依赖
pnpm的方式: 它会在node module文件夹里面,生成我们package里面直接依赖的文件夹(但是这些都是符号链接(软链接)). 所以我们不能再直接引用间接依赖B. 但是他会在node module文件夹里面多一个目录 .pnpm. 在里面,他会把所有的依赖的拍平,这里面存的全都是硬链接.外层的符号链接,就是指向这里硬链接对应的位置. 硬链接直接指向源文件在磁盘中的位置. 相当于一个变量指向一个堆内存(所以一个堆内存,可能有多个硬链接). 这样我们下载都所有的依赖文件,都存在了 pnpm stroe这个目录下面.这样就不会有重复.多个项目可以共享这个目录.这是pnpm下载速度快的,最根本原因.还有一个原因是pnpm可以并行下载.
补充说明:
软连接(也称符号链接),他们是一个快捷方式,相当于桌面上的图标,里面存储的东西,其实只有文件的目标地址这个字符串,但是文件系统会自动打开对应的文件.
硬链接是对文件地址的应用,和复制文件,不一样,是始终只有一个源文件的. 相当于是源文件的指针
软连接在这里可以看硬链接的指针,即为: 指针的指针.
pnpm更新依赖的方式
pnpm store 里面的文件夹,文件都是通过哈希来命名的. 这样它可以精确到单个文件,对于不同版本的依赖,它会对于2个版本文件夹里面文件的哈希值,这样它只会增加有变化的那个文件,而不是整个项目的新增.
pnpm的优点:
通过上述说明,我们可以推断出:1. 快(没有重复的),不占磁盘空间.依赖统一管理.便于模块化和项目合并,更新,重构,等等操作.
pnpm原理示意图
关于pnpm的一些补充知识点:
1. 在项目打包时,打包工具,可以通过这些软硬链接,来对电脑磁盘进行访问,从而来打包对应所需要的依赖.
2. Monorepos(单一代码库)是多个项目(甚至包括java等其他语言),一个项目的不同版本合在一个项目里面,集中管理. 多合一.
3. 微前端,是一个前端项目,拆成不同的模块来分开开发,测试. 一拆多
4. 项目的打包和构建主要是由构建工具(如 Webpack、Vite、Rollup 等)来处理的,而不是由包管理工具(如 pnpm、npm、yarn)直接负责。因此,pnpm 在打包构建过程中的优势可能不如它在依赖管理和下载过程中的优势那么明显。
5. pnpm、yarn、cnpm 等包管理工具都是在 npm 的基础上进行了一些改造和优化,以解决 npm 在某些方面的不足,如性能、依赖管理、网络问题等。所有这些工具都是在 Node.js 环境中运行的,它们都依赖于 Node.js 提供的 API 来执行文件系统操作、网络请求等。虽然它们提供了一些不同的特性和优化,但它们都是构建在 npm 生态系统的核心概念之上,并且旨在提高开发者使用 npm 时的体验。
6. 前端包构建工具发展史:
A. CDN,压缩包: cdn失效,文件过大
B. 老版本的npm: 多个重复依赖 文件可能嵌套过深,window找不到过长路径的文件 单线程安装,解析
C. Npm V3 :扁平化依赖 问题是 不同版本的同一依赖,还是会重复安装,而且第二次来的同一个依赖(不同版本)才会在父依赖的文件夹中有指向. 会有幽灵依赖
D. Yarn: 推出了lock文件,保障每一次打包运行,都是相同的版本的依赖. 所有的依赖都是统一扁平(全局的缓存目录),同一依赖的不同版本,在各自的父依赖里面都有指向. 并行下载(多线程) 支持离线,之前有过缓存的依赖,即使没有网络,也能使用.
7. pnpm的问题:可能有的文件系统不支持,生态发展不如npm,第一次慢, 因为他会访问我电脑其他磁盘位置,所以需要新的权限和可能导致一些安全问题.缓存要及时更新.兼容npm的老项目时,可能有问题.
8. 定期通过pnpm store prune 来清理pnpm-store目录下的依赖