如何将 NPM 命令过滤到工作空间模式(如过滤、包含、排除、glob、grep 或子目录)?

use*_*ca8 2 npm npm-workspaces

我想组织一个大型 NPM monorepo,以便我可以根据类别或模式在许多(但不是全部)工作区上运行命令。

这可以通过子目录,或者通过工作区名称中的模式(例如前缀或后缀),但我看不到任何方法可以单独在 NPM 中执行任何操作。


Yarn >= 2中,可以使用--include--exclude上具有 glob 模式的标志yarn workspaces foreach,例如:

yarn workspaces foreach --include "@namespace/plugin-*" --include "@namespace/preset-*" run build
Run Code Online (Sandbox Code Playgroud)

plugin-...并且使用该名称空间和或前缀构建所有工作区preset-


lerna中,该--scope标志还采用允许模式的全局变量,例如:

lerna run --scope "@namespace/plugin-*" --scope "@namespace/preset-*" run build
Run Code Online (Sandbox Code Playgroud)

但在NPM中,据我在v7v8的 NPM 工作区文档中看到,它似乎没有相同的功能:

  • 它有一个标志--workspace,可以多次使用来创建数组,但似乎只接受确切的工作区名称,
  • ...以及一个--workspaces似乎在所有工作区中运行的标志,

...但我看不到任何方法可以在目录中的所有工作区或匹配模式的所有工作区上运行。我真的不想在每个脚本中按名称列出每个工作区,因为会有很多工作区。

use*_*ca8 7

它没有记录(在询问时),但 NPM可以通过为标志指定一个路径作为其值,将工作区命令过滤到工作区的子目录--workspace。例如:

npm run --workspace packages/presets --workspace packages/plugins build
Run Code Online (Sandbox Code Playgroud)

这将找到直接位于$project_root/packages/presets/或 中的工作空间$project_root/packages/plugins/,但不会找到这些子目录的子目录中的工作空间。

可以使用 包含更深层次的嵌套子目录/**,例如:

npm run --workspace packages/** build
Run Code Online (Sandbox Code Playgroud)

上面的示例适用于组织到子目录中的工作区,在 package.json 中定义如下:

  "workspaces": [
    "packages/plugins/*",
    "packages/presets/*",
    ...more
  ],
Run Code Online (Sandbox Code Playgroud)

...或者像这样的包罗万象:

  "workspaces": [
    "packages/**",
    ...more
  ],
Run Code Online (Sandbox Code Playgroud)

虽然--workspace在撰写本文时,指向工作区的子目录而不是单个工作区似乎没有在任何地方记录,但它确实似乎是一个有意的、有计划的、受支持的功能。我在其中一个 rfcs 深处发现了一条建议它的注释:

注意:不支持将 Glob 作为有效的 --workspace 参数值,建议的替代方案是使用 npm --workspace=,其中是包含多个工作空间的文件夹。

我找不到任何明确说明该提案已实施的内容,但我尝试将我的 monorepo 重新组织到子目录中并使用带有该--workspace标志的子目录,并且它起作用了。

他们在工作区名称中选择路径而不是全局模式(如yarn和lerna)的原因似乎是因为:

在各种受支持的 shell 和操作系统中支持 glob 的许多陷阱