在搞AI项目的时候,代码库通常不会只有一个模块。你可能会有一个用Python写的后端服务,专门跑模型;一个用TypeScript和React写的前端界面,用来展示结果和交互;可能还有一个共享的工具包,前后端都用得到。这种结构叫Monorepo,就是把所有相关的项目都放在一个代码仓库里。管理这种复杂项目,依赖和脚本命令会变得很头疼,这时候pnpm就派上用场了。它比npm和Yarn更快,也更省硬盘空间,特别适合管理这种多包仓库。
下面我就跟你聊聊,在AI项目开发中,具体会用到哪些pnpm指令,它们都是干嘛的。
基础中的基础:安装和管理依赖
这部分指令是你每天都要打交道的,跟吃饭喝水一样平常。
1. pnpm install 或 pnpm i
这个指令是最基本的。当你的项目里有一个 package.json 文件,里面声明了项目需要的所有依赖,你只要在项目根目录运行 pnpm install,它就会把这些依赖全部装好。 比如,你的AI项目前端部分需要React,后端可能需要Express.js来提供API服务,这些都会在这一步被安装。
pnpm牛的地方在于它的工作方式。它不会像npm那样在每个项目里都复制粘贴一份依赖文件,而是用一种叫“硬链接”的方式,把所有依赖统一存放在一个地方。 这样,不管你有多少个子项目都依赖同一个包,硬盘上实际只存了一份。对于动辄就有很多依赖的AI项目来说,能省下不少硬盘空间。
举个例子,假设你的前端和后端都需要axios这个库来发网络请求。你只需要在各自的package.json里声明,然后跑一次pnpm install,pnpm就会处理好链接,而不是真的装两遍。
2. pnpm add <package-name>
当你需要给项目添加新的依赖时,就用这个指令。比如,你想给前端项目加一个图表库,可以进入前端项目的目录,然后运行:
pnpm add echarts-for-react
这行命令会做几件事:
* 下载 echarts-for-react 这个包。
* 把它加到当前目录 package.json 文件的 dependencies 里面。
* 在 node_modules 里创建链接。
如果你想装一个只在开发时才用的工具,比如测试库或者代码格式化工具,可以加上 -D 参数:
pnpm add -D jest
这会把jest加到devDependencies里,这样项目打包上线时就不会包含这些开发用的工具,减小最终包的体积。
3. pnpm remove <package-name>
很简单,就是移除一个不再需要的依赖。 比如你后来发现echarts-for-react不好用,想换掉它,就运行:
pnpm remove echarts-for-react
它会从package.json和node_modules里把这个包彻底清理掉。
Monorepo项目的核心:工作区(Workspace)指令
AI项目通常是Monorepo结构,pnpm对这种结构有原生支持,这也是它如此受欢迎的重要原因。 你需要在项目根目录创建一个 pnpm-workspace.yaml 文件,来告诉pnpm你的哪些文件夹是子项目。
文件内容可能长这样:
yaml
packages:
- 'packages/*'
- 'apps/*'
这表示packages和apps目录下的所有文件夹都是独立的子项目。
配置好工作区之后,下面这些带 -r 或 --filter 参数的指令就变得非常有用了。
1. pnpm install -r
这里的 -r 是 --recursive(递归)的缩写。在Monorepo的根目录运行 pnpm install (其实现在新版的pnpm在工作区里 pnpm install 会默认处理所有子项目),它会读取所有子项目的package.json文件,然后把所有依赖一次性全装好。 这比你一个一个文件夹进去单独装要快得多。
2. pnpm add <package-name> -r --filter <project-name>
这个指令组合非常强大。-r 表示这是一个递归操作,--filter 则用来指定具体要操作哪个子项目。
假设你的Monorepo里有一个叫webapp的前端项目和一个叫server的后端项目。现在你想给webapp添加React,但不想影响到server。你可以这样做:
pnpm add react -r --filter webapp
这里的webapp是apps/webapp/package.json里name字段的值。这样,react就只会被安装到webapp这个子项目里。
如果你想给所有项目都装上某个工具,比如prettier用于代码格式化,你可以这样做:
pnpm add prettier -D -r
-D表示这是开发依赖,-r表示对所有子项目生效。
3. 在子项目之间共享代码
这是Monorepo的精髓。比如,你有一个packages/utils的共享工具包,里面有一些数据处理函数,前端webapp和后端server都想用。
首先,packages/utils/package.json里会有一个名字,比如"name": "@my-ai-project/utils"。
然后,在webapp项目里,你不需要把它发布到npm上再安装。你直接像安装普通依赖一样运行:
pnpm add @my-ai-project/utils -r --filter webapp
pnpm会自动识别出这是一个工作区内部的包,它不会去网上下载,而是直接在webapp的node_modules里创建一个指向packages/utils的符号链接。这样一来,只要你在utils包里改了代码,webapp里就能立刻用上最新的版本,开发联调非常方便。
运行脚本:自动化你的工作流
每个子项目通常都会在package.json的scripts里定义一些脚本,比如启动开发服务、打包、跑测试等。
1. pnpm <script-name>
你可以进入具体的子项目目录,然后运行脚本。比如进入apps/webapp,然后运行:
pnpm dev
这会执行webapp的package.json里定义的dev脚本,启动前端的开发服务器。
2. pnpm -r <script-name>
如果你想同时对所有子项目执行同一个脚本,这个指令就很有用。比如,你想把所有子项目都打包一遍:
pnpm -r build
pnpm会去所有子项目里找build脚本并执行它。 它还会很聪明地分析项目间的依赖关系,确保被依赖的包(比如utils)会先被打包。
3. pnpm -r --parallel <script-name>
如果各个子项目的脚本之间没有依赖关系,比如跑代码检查(lint),你就可以让它们并行执行来节省时间。
pnpm -r --parallel lint
这样,所有子项目的lint脚本会同时开始跑,而不是一个接一个地等,速度会快很多。
其他实用指令
1. pnpm list 或 pnpm ls
查看当前项目安装了哪些依赖,以及它们的版本和相互关系。 如果你在Monorepo的根目录运行pnpm ls -r,它会列出所有子项目的依赖情况。
2. pnpm outdated
检查项目中有哪些依赖已经过期了,有新版本可以更新。在维护项目时,定期跑一下这个指令是个好习惯。
3. pnpm update 或 pnpm up
这个指令会根据你在package.json里定义的版本范围(比如^1.2.3),把依赖更新到最新的兼容版本。
pnpm up -r -L
这条指令会递归地(-r)检查所有子项目的依赖,并把它们更新到最新的版本(-L表示--latest)。
4. pnpm store prune
前面说过,pnpm会把所有包装在一个全局的store里。时间长了,有些旧版本的包可能已经没有任何项目在用了,但它们还占着硬盘空间。运行这个指令可以把这些没用的包清理掉,释放磁盘空间。
总的来说,在AI项目开发中,pnpm的这些指令覆盖了从项目初始化、依赖管理到脚本执行的整个流程。特别是它的工作区功能,让管理复杂的Monorepo变得简单直接,这对于组件繁多、前后端分离的AI应用来说,确实能解决很多实际问题。





评论前必须登录!
注册