pnpm 是一种替代 npm 的包管理工具,具有高效性和节省磁盘空间的特点。它在前端开发中的作用和优势主要体现在以下几个方面:pnpm 中文网站
pnpm 是什么
pnpm - 速度快、节省磁盘空间的软件包管理器
pnpm 在前端开发中的作用和优势
1. 高效的包管理
- 快速安装:pnpm 使用内容寻址存储依赖包,允许重复使用相同版本的包,极大地提高了安装速度。
- 链接的依赖:pnpm 在安装包时,会将包以符号链接的方式存储,减少了文件的重复拷贝。
2. 节省磁盘空间
- 冻结依赖:pnpm 将依赖包安装到全局存储区,每个项目只存储符号链接而不是复制整个包,这样可以有效节省硬盘空间。
- 共享依赖:多个项目可以共享相同版本的依赖,避免不必要的磁盘开销。
3. 强制一致性
- 严格的依赖管理:pnpm 会检查每个包的依赖关系,以确保所有包都正确满足其依赖项。这有助于避免依赖冲突和不一致问题。
- 使用
shamefully-hoist
:pnpm 允许设置shamefully-hoist
选项,将部分依赖提升至顶层。这在某些特定情况下可以解决依赖问题。
4. 更好的工作区支持
- 工作区(Workspaces) :pnpm 对工作区有很好的支持,允许在单一的仓库中管理多个包,有助于管理大型项目或微服务架构。
5. 更强的兼容性
- 兼容 npm Script:pnpm 支持 npm 的所有脚本,可以与现有项目无缝集成。使用 pnpm 安装后,所有 npm 脚本依然可以正常工作。
6. 简单易用
- 命令行接口:pnpm 的命令行接口与 npm 类似,大多数命令都可以直接替换成 pnpm 使用,例如
pnpm install
、pnpm add
等,降低了切换的学习成本。
7. 开发体验
- 锁定文件:pnpm 自动生成
pnpm-lock.yaml
文件以锁定依赖,确保团队成员或 CI/CD 系统在安装时使用相同版本的依赖。
小结
pnpm 在前端开发中的作用主要是提高包管理的效率,节省磁盘空间,确保依赖的一致性,提升开发体验,尤其适合处理大型项目或多包仓库。开发者可以根据项目需求选择使用 pnpm,以享受其带来的优化和便利。
pnpm安装
1. 安装 Node.js
确保你已经安装了 Node.js。你可以通过以下命令检查是否已经安装:
node -v
如果尚未安装 Node.js,可以从 Node.js 官网 下载并安装。
2. 使用 npm 安装 pnpm
在终端中运行以下命令以全局安装 pnpm:
npm install -g pnpm
3. 验证安装
安装完成后,可以通过以下命令验证 pnpm 是否成功安装:
pnpm -v
如果返回 pnpm 的版本号,则说明安装成功。
4. 使用 pnpm
一旦安装完成,你可以开始使用 pnpm 来管理你的项目依赖。例如:
-
初始化新项目:
pnpm init
-
安装依赖:
pnpm install <package-name>
-
安装开发依赖:
pnpm add <package-name> --save-dev
-
卸载依赖:
pnpm remove <package-name>
-
更新依赖:
pnpm update
5. 工作区支持
如果你在一个多包项目(工作区)中使用 pnpm,可以通过以下命令来初始化工作区:
pnpm init -w
pnpm 常用命令
基本命令
-
初始化项目:
# 创建一个新的 `package.json` 文件 pnpm init
-
安装依赖:
# 安装 `package.json` 中列出的所有依赖 pnpm install
-
安装特定依赖:
pnpm add <package-name>
安装指定的包,并将其添加到
dependencies
中。 -
安装开发依赖:
# 安装指定的包,并将其添加到 `devDependencies` 中 pnpm add <package-name> --save-dev
-
卸载依赖:
# 卸载指定的依赖包 pnpm remove <package-name>
-
更新依赖:
# 更新项目中所有依赖到最新版本 pnpm update
-
更新特定依赖:
# 更新指定的依赖包 pnpm update <package-name>
锁定和查看
-
查看已安装的依赖:
# 列出项目中已安装的所有依赖 pnpm list
-
查看全局安装的包:
# 列出全局安装的依赖,不显示子依赖 pnpm list -g --depth 0
-
生成锁定文件:
# 只生成或更新 `pnpm-lock.yaml` 文件,不实际安装依赖 (一般都是 pnpm i/add 后自动生成即可) pnpm install --lockfile-only
工作区支持
-
初始化一个工作区:
# 创建一个工作区的 `package.json` 文件 pnpm init -w
-
在工作区中添加包:
# 在工作区中添加指定的包 pnpm add <package-name> --workspace
脚本命令
-
运行脚本:
# 运行在 `package.json` 中定义的脚本 pnpm run <script-name>
其他常用选项
-
清除缓存:
# 清理不再使用的缓存包 pnpm store prune
-
查看帮助信息:
# 显示所有 pnpm 命令的帮助信息 pnpm help
配置文件
pnpm-lock.yaml 和 package.json文件的区别(类似npm 文章这里不过多赘述可看# 程化之包管理器npm,一次说明白前端在中的使用
在使用 pnpm 作为包管理工具时,可以利用 .npmrc
文件来配置 npm 和 pnpm 的行为。以下是一些常用的 .npmrc
配置属性,以及它们的作用:
1. registry
-
描述:指定 npm 包的注册表地址。
-
示例:
registry=https://registry.npmjs.org/
如果使用其他源,比如淘宝源,可以写成:
registry=https://registry.npm.taobao.org/
2. always-auth
-
描述:在每次请求中是否始终发送身份验证信息。
-
示例:
always-auth=true
3. scope
-
描述:指定 npm 包的作用域,通常用于组织或私有包。
-
示例:
scope=@my-org
4. authToken
-
描述:用于身份验证的访问令牌,可以用来访问私有库。
-
示例:
//registry.npmjs.org/:_authToken=YOUR_AUTH_TOKEN
5. cache
-
描述:定义 npm 的缓存目录,用于存放下载的包。
-
示例:
cache=/path/to/npm/cache
6. save-exact
-
描述:安装依赖时是否将其版本保存为精确版本,而不是使用波浪号或插入号。
-
示例:
save-exact=true
7. strict-peer-dependencies
-
描述:严格检查对等依赖。如果设置为
true
,则在未满足某个对等依赖的情况下安装会失败。 -
示例:
strict-peer-dependencies=true
8. shamefully-hoist
-
描述:如果设置为
true
,pnpm 会将所有依赖提升到顶层node_modules
目录,可能帮助解决某些依赖问题。 -
示例:
shamefully-hoist=true
9. link-workspace-packages
-
描述:在工作区中使用时,是否将工作区中的包以符号链接的方式连接到
node_modules
。 -
示例:
link-workspace-packages=true
10. scripts-prepend-node-path
-
描述:控制
node
可执行文件的路径,以确保可以在运行 npm 脚本时找到node
。 -
示例:
scripts-prepend-node-path=auto
特别的配置文件 pnpm-workspace.yaml
(monorepo工作区,正常项目无需,UI组件库 第三方插件等框架中会比较多使用到)
pnpm-workspace.yaml
是一个用于配置 pnpm 工作区的文件,主要用于定义和管理包含多个包的单一代码库(monorepo)的结构。以下是 pnpm-workspace.yaml
文件的主要作用和功能:
1. 定义工作区
-
作用:该文件用于明确声明当前项目是一个工作区,并定义工作区中包含的所有子包。
-
示例:
packages: - 'packages/*' # 包含 packages 目录下的所有子包 - 'libs/*' # 包含 libs 目录下的所有子包
2. 配置包的路径
-
作用:通过指定路径模式,可以方便地管理多包项目中哪些文件夹是包。
-
示例:
packages: - 'packages/*' - 'services/*'
3. 共享依赖
- 作用:在工作区中,所有共享依赖仅会被安装一次,而不是在每个子包中重复安装,从而减少磁盘空间的使用,提高安装速度。
- 示例:在根目录的
package.json
中定义共享依赖,所有子包都可以使用它们。
4. 方便的开发和测试
- 作用:统一管理多个包,使得在工作区中开发、测试和发布变得更加高效和简便。可以通过在根目录运行命令来安装、更新或测试所有包。
- 示例:通过
pnpm install
指令,工作区中的所有包都会被统一处理。
5. 版本和锁定文件管理
- 作用:工作区中的所有包使用同一个
pnpm-lock.yaml
锁定文件,确保所有包的依赖版本一致性,有助于避免出现不兼容性的问题。
6. 支持 linting 和其他脚本
- 作用:可以在工作区根目录中集中管理 linting、构建、测试等的运行命令,方便进行批量操作
pnpm解决了什么npm没解决的问题
1. 磁盘空间的浪费
- 问题:npm 在每个项目中都会单独安装依赖,即使是相同版本的依赖也会重复存储,导致磁盘空间的浪费。
- 解决方案:pnpm 使用内容寻址存储和符号链接,允许多个项目共享相同版本的依赖。这样,只有一份依赖会被存储在硬盘中,从而显著节省磁盘空间。
2. 安装速度
- 问题:npm 在处理多个已安装依赖时,安装速度可能较慢,特别是在大项目中。
- 解决方案:pnpm 在安装依赖时通过使用缓存和符号链接来提高效率,减少安装时间,特别是在安装多个包时。
3. 严格的依赖管理
- 问题:npm 对于对等依赖的处理较宽松,可能导致不一致性和依赖冲突,尤其是在大型项目中。
- 解决方案:pnpm 强制执行对等依赖的解析,确保所有依赖都满足其声明的要求,从而减少潜在的版本冲突和不兼容问题。
4. 工作区支持
- 问题:虽然 npm 在现代版本中增加了工作区的支持,但在处理大型 mono-repo 项目时可能仍然存在一些限制。
- 解决方案:pnpm 的工作区模式非常强大,能够轻松管理多个包,并且允许共享依赖,使得开发和集成变得更加高效。
5. 安装过程中的一致性
- 问题:npm 可能在不同的环境(如 CI/CD 系统和开发者本地)中产生不同的结果,特别是在安装依赖的途中。
- 解决方案:pnpm 生成的
pnpm-lock.yaml
文件能够精确锁定所有依赖及其版本,确保在不同环境中的安装结果一致。
6. 性能
- 问题:npm 的性能在面对大量依赖时可能会有所下降,特别是在对依赖进行合并和更新时。
- 解决方案:pnpm 的模式通过避免依赖重复安装,并利用有效的缓存策略,显著提升了性能。
总结
pnpm 解决了幻影依赖(phantom dependencies)问题,这也是它相较于 npm 的一个显著优点。
什么是幻影依赖(又叫幽灵依赖)?
幻影依赖是指某个包在使用时,它的代码依赖于另一个包,但该包并没有明确列在 dependencies
或 devDependencies
中。当这个依赖(通常是直接依赖的间接依赖)未被安装在项目的 node_modules
目录中时,可能会导致运行时错误,特别是在某些情况下,代码可能会假设这个依赖是存在的。
举个例子
假设你有以下两个包:
-
package-a
:{ "name": "package-a", "version": "1.0.0", "dependencies": { "package-b": "^1.0.0" } }
-
package-b
:{ "name": "package-b", "version": "1.0.0" }
幻影依赖的示例
现在,假设有一个第三个包 package-c
,使用了 package-a
:
{
"name": "package-c",
"version": "1.0.0",
"dependencies": {
"package-a": "^1.0.0"
}
}
在这个例子中,package-c
依赖于 package-a
,而 package-a
又依赖于 package-b
。正常情况下,如果你运行 npm install
,package-b
会被安装在 package-a
的 node_modules
中。
假设 package-b
作为一个对 package-c
至关重要的依赖,它在 package-a
的实现中被使用,但在 package-c
的 package.json
中没有明确列出 package-b
。
运行时错误
如果 package-c
的代码中直接调用了 package-b
的功能,代码会抛出一个错误,因为在 package-c
中并没有安装 package-b
,尽管它的某个依赖(package-a
)实际上依赖了 package-b
。运行时可能会出现像这样的错误:
Error: Cannot find module 'package-b'
解决幻影依赖
为了解决这个问题,应该在 package-c
的 package.json
中明确列出对 package-b
的依赖:
{
"name": "package-c",
"version": "1.0.0",
"dependencies": {
"package-a": "^1.0.0",
"package-b": "^1.0.0" // 明确添加对 package-b 的依赖
}
}
现在,任何使用 package-c
的人都能确保他们的环境里有 package-b
,从而避免幻影依赖引起的运行时错误。
pnpm 如何解决幻影依赖的问题?
-
严格的依赖管理:
- pnpm 强制要求所有的依赖都必须在
package.json
中进行显式声明。这意味着如果某个包依赖于其他包,那么这些包也需要在相应的dependencies
或devDependencies
中列明,避免出现没有明确定义的依赖。
- pnpm 强制要求所有的依赖都必须在
-
建立符号链接:
- 与 npm 使用传统的
node_modules
结构不同,pnpm 使用符号链接和内容地址存储。即使是对等依赖,pnpm 也会记录并确保依赖关系的完整性,从而减少或消除幻影依赖的风险。
- 与 npm 使用传统的
-
对等依赖的严格解析:
- pnpm 在安装过程中将检查对等依赖(peer dependencies),如果未满足,npm 会发出警告。这样可以确保在使用某个依赖时,其所需的对等依赖在正确的位置和版本中安装。
结论
通过这些机制,pnpm 使得项目的依赖关系更加清晰和可靠,显著减少了幻影依赖的问题。这种严格的依赖管理策略有助于提升代码的稳定性和可维护性。因而依据上面各种分析,pnpm优势瞬间突出,也是目前pnpm这么多人喜欢使用的原因。。。顺势而为吧,目前前端的技术发展迅猛,还是要多多接触新概念新知识,扎实基础。。。