如何在Yarn PnP monorepo中开发外部npm包并在内部包测试?
问题描述
我维护着一个大型Yarn PnP monorepo(包含约30个包和3个微应用),其中内部包package-b依赖外部npm包package-a(该包使用npm作为包管理器,不属于当前monorepo)。请问如何开发外部npm包package-a,并在Yarn PnP monorepo的package-b中进行测试?
使用版本
$ yarn --version 4.1.1 $ node --version # (所有项目版本一致) v18.15.0 $ npm --version 9.5.0
已尝试的方法
Yarn link
在package-a目录执行:
$ cd /Users/user/gitlab.com/org/package-a $ npm install $ npm run build $ yarn link
切换到package-b目录执行链接命令:
$ cd /Users/user/gitlab.com/org/monorepo/package-b $ yarn link package-a
触发报错:
Usage Error: Invalid destination 'package-a'; Can't link the project to itself $ yarn link [-A,--all] [-p,--private] [-r,--relative] ...
已确认并非链接同一包,报错不符合实际场景。
使用resolutions配置portal
在package-b的package.json中添加:
{ ... "resolutions": { "package-a": "portal:/Users/user/gitlab.com/org/package-a" }, ... }
执行monorepo级别的yarn命令全量重建所有包,但修改未生效。
在dependencies中配置portal
在package-b的package.json中添加:
{ "dependencies": { "package-a": "portal:/Users/user/gitlab.com/org/package-a", } }
构建monorepo时出现错误:
Module not found: Error: Can't resolve 'package-a' in '/Users/myuser/gitlab.com/org/monorepo/.yarn/__virtual__/package-b-virtual-126d6aafbe/1/packages/package-b/dist/components/SomeComponent/util' @ ../..
已确认package-a的dist目录存在且构建完成,且能在其他npm项目中正常使用。
解决方案
针对Yarn 4.x PnP monorepo开发外部npm包的场景,推荐以下三种可靠方案:
方案一:修正portal:协议配置(推荐)
之前的portal配置失效或报错,大概率是路径范围或包入口配置问题,按以下步骤操作:
- 检查
package-a的package.json,确保main/module字段指向正确的构建产物路径,比如:{ "main": "./dist/index.js", "module": "./dist/index.esm.js" } - 在monorepo根目录的
package.json中添加resolutions(而非仅在package-b中配置):{ "resolutions": { "package-a": "portal:/Users/user/gitlab.com/org/package-a" } } - 执行命令让Yarn重新解析依赖并生成PnP映射:
yarn install --force # 若使用VSCode,执行以下命令确保编辑器能识别依赖 yarn dlx @yarnpkg/sdks vscode - 修改
package-a代码后,重新执行npm run build即可,无需重启monorepo服务,Yarn会自动加载最新构建产物。
方案二:本地tar包引入
如果portal协议仍存在兼容性问题,可通过本地tar包方式引入:
- 在
package-a目录执行打包命令:cd /Users/user/gitlab.com/org/package-a npm install && npm run build yarn pack # 生成类似 package-a-1.0.0.tgz 的本地包文件 - 在
package-b的package.json中修改依赖指向该tar包:{ "dependencies": { "package-a": "file:/Users/user/gitlab.com/org/package-a/package-a-1.0.0.tgz" } } - 回到monorepo根目录执行
yarn install,即可加载本地包进行测试。 - 每次修改
package-a后,重新打包并执行yarn install即可更新依赖。
方案三:临时加入Yarn Workspace(适合长期并行开发)
若需要长期同时开发package-a和monorepo,可将package-a临时加入monorepo的workspace:
- 在monorepo根目录的
package.json中修改workspaces字段,添加package-a的路径:{ "workspaces": [ "packages/*", "/Users/user/gitlab.com/org/package-a" ] } - 执行
yarn install,Yarn会将package-a作为内部workspace包管理,此时package-b会直接使用本地的package-a代码。 - 开发完成后,移除
workspaces中的package-a路径,恢复原依赖配置即可。
内容的提问来源于stack exchange,提问作者mitchkman
相关产品推荐
相关产品推荐

