• 亮色
  • 深色
  • 自动
  • RSS 订阅

    pnpm 的 workspace

    2024-07-05

    介绍

    pnpm 内置了对 monorepo1 的支持,通过该支持,可以实现一个存储库(workspace)存放多个项目。

    workspace 协议

    优先装本地的 package

    .npmrc 里指定 link-workspace-packagestrue,可以使 workspace 内的 package 安装依赖时优先查找当前 workspace 里的 package。

    假如 workspace 里有个 bar package 依赖 foo package,并且 workspace 里存在一个 foo package,然后这个 foo 版本为 1.0.0,那么当 bar package 安装 foo@1.0.0 依赖项时,会优先安装这个 workspace 里的 foo package。但是如果 bar package 安装 foo@2.0.0,那么由于 workspace 里的 foo package 版本对不上,就会去找 npm 上的 foo@2.0.0 package 进行安装。

    所以这个配置有可能带来未知的结果。

    关于 workspace 的设置可以参考:.npmrc | pnpm

    要依赖 workspace 内其他 package,可以像这样添加依赖项: "foo": "workspace:*"。这表示依赖 workspace 内的 foo package,并且不限定版本。

    如果想以别名的方式使用依赖,可以像这样添加依赖项:"@repo/foo": "workspace:foo@*"

    在发布的时候,别名会被转成常规的别名依赖项,像上面的会转成:"@repo/foo": "npm:foo@1.0.0"

    命令行里的安装方式

    需要注意的是在命令行里安装好像指定不了具体版本,不管指定 * 还是具体版本名,添加到 package.json 里都是 ^ 版本。

    # 以依赖名的方式安装
    # 相当于 "foo": "workspace:^"
    pnpm i foo@workspace:^
    
    # 以别名的方式安装
    # 相当于 "@repo/foo": "workspace:foo@^"
    pnpm i @repo/foo@workspace:foo@
    

    以相对路径的方式依赖 workspace package

    假设当前 workspace 有两个 package:

    + packages
      + foo
      + bar
    

    bar 的依赖项中可能有 foo 声明为 "foo": "workspace:../foo"。在发布之前,这些依赖声明会转成为所有包管理器支持的常规版本规范。

    发布 workspace packages

    当 workspace package 打包到存档中时(无论是通过 pnpm pack 还是诸如 pnpm publish 之类的发布命令之一),会通过以下方式动态替换任何工作区:依赖项:

    • 目标工作区中对应的版本(如果使用 workspace:*workspace:~workspace:^
    • 关联的 semver 范围(对于任何其他范围类型)

    例如,如果工作区中有 foobarqarzoo,它们的版本均为 1.5.0,像下面这样:

    {
      "dependencies": {
        "foo": "workspace:*",
        "bar": "workspace:~",
        "qar": "workspace:^",
        "zoo": "workspace:^1.5.0"
      }
    }
    

    那么打包时会自动转换成像下面这样:

    {
      "dependencies": {
        "foo": "1.5.0",
        "bar": "~1.5.0",
        "qar": "^1.5.0",
        "zoo": "^1.5.0"
      }
    }
    

    这个功能允许你依赖本地 workspace package,同时仍然能够将生成的 package 发布到远程注册表,而无需中间发布步骤,package 的用户将能够像任何其他 package 一样使用你发布的 workspace,仍然受益于 semver 提供的保证。

    Release workspace

    对 workspace 内的 package 进行版本控制是一项复杂的任务,pnpm 目前没有为此提供内置解决方案。然而,有两个经过充分测试的工具可以处理版本控制并支持 pnpm:

    故障排除

    如果 workspace 依赖项之间存在循环,pnpm 无法保证脚本将按正常顺序运行。如果 pnpm 在安装过程中检测到循环依赖关系,它将产生警告。如果 pnpm 能够找出哪些依赖项导致了循环,它也会显示它们。

    Footnotes

    1. 又称多包存储库、多项目存储库或整体存储库

    参考