运行时包管理器打包器测试运行器代码检查格式化指南参考博客反馈

bun --filter

使用 --filter 标志在 monorepo 中按模式选择包

--filter(或 -F)标志按模式选择 monorepo 中的包。模式可以是包名称 glob、./path glob、{dir} 目录选择器或 ... 依赖关系。

该标志可与 bun run、bun install、bun add、bun remove、bun update、bun outdated、bun prune 和 bun pm licenses 一起使用。对于包管理器命令,请将标志放在子命令之后(bun install --filter api),因为 bun --filter <pattern> <word> 会将 <word> 作为脚本运行。


匹配

包名 --filter <pattern>

名称模式根据 package.json 中的 name 字段选择包。例如,如果有包 pkg-a、pkg-b 和 other,可以使用 * 匹配所有包,使用 pkg* 仅匹配 pkg-a 和 pkg-b,也可以使用包的完整名称匹配指定包。

包路径 --filter ./<glob>

路径模式以 ./ 开头,并选择目录中匹配该模式的所有包。例如,要匹配 packages 子目录中的所有包,请使用 --filter './packages/**'。要匹配 packages/foo 中的包,请使用 --filter ./packages/foo。

名称模式匹配完整的包名称(core 不会匹配 @acme/core;请使用 @acme/*),并且 * 不会跨越 /。路径模式必须匹配工作区目录本身:./packages 不会选择任何内容,./packages/* 会选择其中的每个直接工作区。

目录 --filter '{<dir>}'

大括号中的目录会选择该目录中或其任意下级目录中的所有工作区,目录路径相对于当前目录解析。--filter '{packages}' 会选择 packages/ 下的所有内容;--filter '{.}' 会选择当前目录的工作区及其下的所有内容。

依赖关系 --filter 'foo...'

在模式后添加 ...,还会选择通过工作区依赖关系关联的工作区:

模式选择
foo...foo 及其直接或传递依赖的工作区
foo^...foo 直接或传递依赖的工作区,不包括 foo 本身
...foofoo 及直接或传递依赖于它的工作区
...^foo直接或传递依赖于 foo 的工作区,不包括 foo 本身

foo 可以是名称 glob 或目录选择器(...{./packages/api})。要排除内容,请将 ! 放在最前面:--filter '!...foo'。

terminal
bun install --filter 'web...'
bun add zod --filter '...^ui'
bun outdated --filter '{./packages/apps}'

bun install 和 bun outdated

默认情况下,bun install 会为 monorepo 中的每个包安装依赖。要为特定包安装依赖,请使用 --filter。

多个 --filter 标志会组合使用:选择所有与正向模式匹配的内容,再排除与 ! 模式匹配的内容。没有匹配任何内容的模式会打印警告。对于 bun add、bun remove、bun update、bun prune 和 bun pm licenses,如果完全没有选择工作区,则会报错。

对于 ./packages 下包含工作区 pkg-a、pkg-b 和 pkg-c 的 monorepo:

terminal
# 安装除 `pkg-c` 以外所有工作区的依赖
bun install --filter '!pkg-c'

# 安装 `./packages` 目录下的包(`pkg-a`、`pkg-b`、`pkg-c`)的依赖
bun install --filter './packages/*'

# 与上面相同,但排除根目录 package.json
bun install --filter '!./' --filter './packages/*'

同样,bun outdated 会显示 monorepo 中所有包的过期依赖,而 --filter 会将命令限制为其中的部分包:

terminal
# 显示名称以 `pkg-` 开头的工作区的过期依赖
bun outdated --filter 'pkg-*'

# 仅显示根目录 package.json 的过期依赖
bun outdated --filter './'

请参阅 bun install 和 bun outdated。


使用 --filter 运行脚本

使用 --filter 标志可以一次在多个包中执行脚本:

terminal
bun --filter <pattern> <script>

假设你有一个包含两个包的 monorepo:packages/api 和 packages/frontend,它们都有一个用于启动本地开发服务器的 dev 脚本。通常,你需要打开两个终端标签页,分别切换到每个包的目录,然后运行 bun dev:

terminal
cd packages/api
bun dev

# 在另一个终端
cd packages/frontend
bun dev

使用 --filter,你可以同时在这两个包中运行 dev 脚本:

terminal
bun --filter '*' dev

两个脚本会并行运行,终端 UI 会显示它们各自的输出:

终端输出

其他模式形式的用法相同:

terminal
# build web and everything it depends on, in dependency order
bun --filter 'web...' build

# test the packages that depend on ui
bun --filter '...^ui' test

# run dev in every package under packages/apps
bun --filter '{./packages/apps}' dev

# lint every package except docs
bun --filter '*' --filter '!docs' lint

只有 ./path 模式可以选择没有 name 的 package.json。如果选中的包都没有该脚本,bun run 会以错误退出(传入 --if-present 则会以 0 退出)。

在工作区中运行脚本

过滤器遵循你的工作区配置:如果你的 package.json 指定了哪些包属于工作区,--filter 只会匹配这些包。在工作区中,--filter 还可以运行位于工作区任意位置的包中的脚本:

terminal
# 包结构
# src/foo
# src/bar

# 在 src/bar 中:运行 src/foo 的 myscript,无需切换目录!
bun run --filter foo myscript

并行和顺序模式

结合 --filter 或 --workspaces 与 --parallel 或 --sequential,可以跨工作区包运行脚本,并带有 Foreman 风格的前缀输出:

terminal
# 并发运行所有匹配包的 "build"
bun run --parallel --filter '*' build

# 顺序运行所有工作区包的 "build"
bun run --sequential --workspaces build

# 在所有包中运行符合通配符的脚本
bun run --parallel --filter '*' "build:*"

# 即使某个包的脚本失败,也继续运行其他脚本
bun run --parallel --no-exit-on-error --filter '*' test

# 在所有包中运行多个脚本
bun run --parallel --filter '*' build lint

Bun 会在每行输出前加上包名和脚本名(pkg-a:build | ...)。如果没有使用 --filter/--workspaces,则只会加上脚本名作为前缀(build | ...)。如果某个包的 package.json 没有 name 字段,Bun 会改用相对于工作区根目录的路径。

将 --if-present 与 --workspaces 一起使用,可以跳过没有指定脚本的包,而不报错。

依赖顺序

Bun 会在运行脚本时遵循包的依赖顺序。假设你有一个包 foo,它依赖于工作区中的另一个包 bar,并且两者都有一个 build 脚本。当你运行 bun --filter '*' build 时,只有在 bar 完成后,foo 才会开始运行。