返回
创建于
状态公开
既然您想结合起来了解,通常是指将 -C (Change directory) 与 pnpm 在 Monorepo(多包仓库)中最常用的 -F (Filter) 参数进行对比。
理解这两者的区别,对于高效管理项目至关重要。
我们可以用一个通俗的例子来区分:
-C(基于物理路径): 就像快递员,只认门牌号(比如:去 "3楼左边的房间" 送货)。-F(基于逻辑名称): 就像公司前台,认的是人名/部门名(比如:把文件交给 "财务部" 或 "张三")。
1. pnpm -C:物理位置切换
它的逻辑非常简单粗暴:“去那个文件夹,执行命令”。
- 依据: 文件系统路径(Folder Path)。
- 场景: 你明确知道文件夹在哪里,或者你只是单纯想在一个特定目录下跑个命令,不在乎它是不是 Monorepo 的一部分。
- 缺点: 路径如果变了(比如重构了文件夹结构),命令就挂了。
1# 只要 apps/web 这个文件夹存在,就能跑
2pnpm -C ./apps/web add lodash2. pnpm -F (即 --filter):智能项目筛选
这是 pnpm 管理 Monorepo 的核心神器。它的逻辑是:“在整个工作区里,找到名字叫这个的包,给它执行命令”。
- 依据:
package.json中的name字段,或者目录通配符。 - 场景: 多包管理、批量操作、依赖关系构建。
- 优点:
- 更稳定: 只要
package.json里的名字没变,你把文件夹移到哪里去都无所谓。 - 不仅是单选: 可以同时选中多个包。
- 懂依赖关系: 可以连带构建依赖项。
1# 哪怕 apps/web 被移动到了 packages/core-web
2# 只要它的 package.json 里 name 是 "@my-app/web",这行命令依然有效
3pnpm -F @my-app/web add lodash3. 深度对比:为什么 -F 更强大?
假设你有以下结构:
1root/
2├── package.json
3├── pnpm-workspace.yaml
4├── apps/
5│ └── shop (name: @app/shop) -> 依赖于 @lib/ui
6└── packages/
7 └── ui (name: @lib/ui)场景 A:我想给 shop 安装 react
- 用
-C:pnpm -C ./apps/shop add react - 用
-F:pnpm -F @app/shop add react - 结果: 此时两者差不多。
场景 B:我想构建 shop,但前提是它依赖的 ui 必须先构建好
- 用
-C: ❌ 做不到。你必须手动先去 build ui,再去 build shop。 - 用
-F: ✅ 拓扑构建 (Topology)
1# "..." 表示:包含 @app/shop 以及它所有的依赖项
2pnpm -F @app/shop... buildpnpm 会自动分析出:先 build @lib/ui,成功后再 build @app/shop。这是 -C 绝对做不到的。
场景 C:我想给 apps 目录下所有的项目都运行 test
- 用
-C: ❌-C只能接受单一路径。 - 用
-F: ✅ 支持通配符
1pnpm -F "./apps/*" test4. 总结:什么时候用哪个?
| 特性 | -C <路径> | -F <包名> |
|---|---|---|
| 全称 | Change Directory (切换目录) | Filter (过滤/筛选) |
| 定位方式 | 必须写对文件路径 | 根据 package.json 的 name |
| Monorepo 感知 | 无 (纯粹的系统操作) | 有 (知道项目结构) |
| 依赖拓扑 | 不支持 | 支持 (使用 ...) |
| 批量操作 | 不支持 | 支持 (如 -F "apps/*") |
| 主要用途 | 脚本中避免 cd,或单体项目 | Monorepo 开发的标准方式 |
一句话建议:
如果你在维护一个 Monorepo 项目,请尽量养成使用 -F 的习惯,因为它更智能、更符合项目逻辑;只在写 CI 脚本或者处理非 Node 项目目录时使用 -C。
我可以为您做的下一步:
您现在的项目中,pnpm-workspace.yaml 是怎么配置的?如果您想尝试用 -F 来进行增量构建(比如只构建我在 git 中修改过的包),我可以教您如何结合 git 来使用 -F。