🚀🚀🚀 pnpm 实践:挑战将前后端项目合并在 monorepo 项目并保留历史提交信息

1,095 阅读4分钟

前言

最近组里要求我把几个老项目的包管理工具从 yarn 转为 pnpm,因为新项目都使用 pnpm,另外,还要求将前后端(NodeJS)项目使用 monorepo的方式组织在一个仓库里,并且保留历史提交记录!

这里记录下替换和组织过程!

往期精彩推荐

正文

开始之前,需要了解 yarn 和 pnpm 的区别!

前端的包管理工具之所以层出不穷,从官方的 npm 到热门社区的 yarn pnpm方案,再到一些新兴的 bun volta等, 其核心原因是由于依赖包版本更新快,管理越来越复杂,这是一个梗图!

负重前行

目前来说,社区没有完美的解决方案,都是侧重点不用,比如 yarn 可以做到锁文件版本,可以让不同环境的开发者,使用相同版本的依赖包!pnpm 通过硬链接节省磁盘空间,这种机制分别弥补了 npm 在这两种情况下的缺点!

另外,它们都有自己的特色功能,比如:pnpm 内置了 monorepo 管理能力,以及可插拔的 hook 生命周期和插件机制!

yarn 在 v2 中推出了 PNP 机制,抛弃 node_modules 目录,直接从 .pnp.js 加载依赖,加速启动速度,并减少磁盘文件数量,你可以将 .yarn/cache 和 .pnp.js 一起提交到 git,这样 clone 项目后无需再执行 install,即装即用!

说的有点多了,总结就是一句话:

pnpm 通过硬链接节省磁盘空间,并且内置了 monorepo 管理能力!

yarn 通过锁文件版本,有很强的一致性!

而我使用 pnpm 更多的原因是内置的 monorepo 能力!

替换

说干就干,首先删除 node_modules yarn.lock 文件,然后在在 package.json 文件中新增下面的配置,锁定包管理工具和版本:

"engines": {
    "node": ">=18.0.0",
    "pnpm": ">=8.0.0"
},
"packageManager": "pnpm@8.0.0",

然后执行 pnpm install

npm run dev

不出意外,肯定会报错,缺少某个包,这是正常的,因为 yarn 允许使用父级项目的依赖,而 pnpm 是不允许的!

这时候有两种方案,一种是将缺失的包,直接在 pnpm add xxx 添加进来!

另一种方案是允许使用父级依赖: pnpm install --node-linker=hoisted

具体使用哪种方案,你可以先运行下这个命令:

npx --yes depcheck

它可以列举项目中未使用、缺失的包,

Unused、Missing 情况

如果缺失的很多,推荐第二种,不多的话就一个一个下载吧!

组织(重头戏)

新建文件夹,例如:demo,然后初始化

mkdir demo
cd demo
pnpm init

新建 pnpm-workspace.yaml,新增如下配置

packages:
  - 'packages/*'

新建 packages 文件夹,存放前后端子项目!

接下来是重头戏了,怎么保留原始 git 历史信息的情况下,将前后端项目保存在一个 git 仓库里?

首先你得下载一个工具库 git-filter-repo:

brew install git-filter-repo

然后初始化git,

git init

拉取一个裸仓库

git clone --bare https://xxxx/fe.git

然后进入这个临时项目

cd fe.git

使用 git-filter-repo 工具合并历史记录

git filter-repo --to-subdirectory-filter packages/fe

添加临时仓库

cd ..
git remote add fe ../demo/fe.git

拉去最新代码

git fetch fe

将 fe 的代码 合入过来

git merge fe/master --allow-unrelated-histories -m "feat: 合并代码"

清理临时临时仓即可

git remote remove fe

验证下是否有历史记录

git log -- packages/fe

并且可以看到在 packages 已经有了我们前端的代码了

接着重复上面的操作完成后端代码的迁移即可!

操作之后,你就可以看到完整的带有 git 历史记录的 monorepo 项目了!

我的历史记录

最后

今天的分享就这些了,希望可以帮助到你!如果文章中有任何问题,欢迎指正!

往期精彩推荐