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

547 阅读4分钟

前言

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

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

往期精彩推荐

正文

开始之前,需要了解 yarnpnpm 的区别!

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

负重前行

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

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

yarnv2 中推出了 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 项目了!

我的历史记录

最后

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

往期精彩推荐