Selecting subsets of projects
Bulk commands like rush build
and rush rebuild
operate on
all projects in the monorepo by default. This becomes expensive as you accumulate more and more projects.
To speed things up, Rush provides a set of command-line parameters for selecting subsets of projects.
Suppose we're working with the following collection of Rush projects:
In the above illustration, the circles represent local projects, not external NPM dependencies.
The arrow from D
to C
indicates that D
depends on C
; this means that C
must be built before
D
can be built. We'll use the rush build
command in the examples given below, but these same parameters
work for any bulk command.
Selection parameters
--to
Possible scenario: Suppose that you have just cloned your monorepo, and now you want to start working
on project B
. You need to build all the things that B
depends on, and also B
itself.
Here's how to do that:
# Build everything up to (and including) project B
rush build --to B
The projects selected by this command are A
, B
, and E
:
--to-except
Possible scenario: In many cases we do not need rush build
to process B
, because our next step
will be to invoke Webpack or Jest in "watch mode" for B
. You can use --to-except
instead
of --to
to exclude B
.
# Build everything up to project B, but not B itself
rush build --to-except B
# Invoke Jest watch mode to build B
heft test --watch
The projects selected by this command are A
and E
:
--from
Possible scenario: Now that we've finished making our changes to B
, we want to build the downstream
projects C
and D
to make sure their tests were not broken by our change. In order to build D
,
we also need to include its dependency G
. The --from
command does this. It will also include A
and E
since they're required by B
. (Since rush build
is incremental, A
and E
will probably get skipped assuming
they are still up to date.)
# Build everything downstream from B, including any implied dependencies
rush build --from B
This command selects everything except for F
:
Compatibility note: If the
rushVersion
setting in your rush.json is older than 5.38.0, then--from
will instead behave like--impacted-by
. The meaning was changed in Rush 5.38.0 because most users expected--from
to include dependencies.
--impacted-by (unsafe)
Possible scenario: Suppose that while working on B
we made some changes to E
. The rush build
incremental analysis assumes that any change to E
requires all its downstream dependents to be rebuilt,
including F
for example. That can be a big set. Maybe you know better -- perhaps you later reverted your change
in E
, or maybe you manually invoked the toolchain so E
is in good shape, or maybe your change to E
is
not relevant right now.
In these situations the --impacted-by
parameter can be handy: It means "Select only those projects
that might be broken by a change to B, and trust me that their dependencies are in a usable state."
# Build B and everything downstream from B, but don't include dependencies
rush build --impacted-by B
The projects selected by this command are B
, C
, and D
:
--impacted-by-except (unsafe)
Possible scenario: This is the same as --impacted-by
except that it does not include B
itself. For example
that might make sense if you already built B
manually while implementing the thing that we now want to test.
# Build everything downstream from B, but don't include dependencies
rush build --impacted-by-except B
The projects selected by this command are C
and D
:
--only (unsafe)
Possible scenario: As its name implies, the --only
parameter adds exactly one project to the selection,
ignoring dependencies.
# Build only B and nothing else
rush build --only B
The --only
parameter is most useful when combined with other parameters. For example, in our narrative above
when we did rush build --impacted-by B
, maybe we had not actually built G
yet. We can include it by
doing rush build --impacted-by B --only G
.
"Unsafe" parameters: The parameters
--only
,--impacted-by
, and--impacted-by-except
can all fail if the required dependencies are not built. These three parameters save time by assuming that you know better than Rush about what really needs to be built. If that assumption is incorrect, you can always dorush build
to get back to a good state.
Selectors
When you use a selection parameter such as rush build --to X
, the argument X
is called a selector.
In the discussion above, we assumed that the selector was always the name of a single Rush project.
Rush supports a variety of other selector syntaxes, some of which can refer to more than one Rush project.
Project name
The simplest selector is the full name of the Rush project, which is the "name"
field from package.json.
Examples:
rush build --to @my-company/my-project-name
rush build --from @my-company/my-project-name
rush list --impacted-by @my-company/my-project-name
If the package name includes an NPM scope such as @my-company
, Rush allows you to omit the scope for brevity
(as long as the unscoped name is not used by some other project in your workspace).
Examples:
rush build --to my-project-name
rush build --from my-project-name
rush list --impacted-by my-project-name
Generally the disk folder of @my-company/my-project-name
would also be called my-project-name
,
a practice which we strongly recommend to avoid confusion. It is important to understand that this selector
is NOT matching the disk folder.
Current folder: .
The folder containing a Rush project's package.json file is called the project folder. If your
shell's current working directory is somewhere under a project folder, then the selector .
provides
a convenient shorthand for referring to that project.
Examples:
cd my-project-name
# Build "@my-company/my-project-name" whose package.json
# is in the current working directory
rush build --to .
cd src
# The "." selector can also be resolved from a subfolder
# such as my-project-name/src
rush list --to-except .
Modified projects: git:
By providing a Git reference expression
(branch, tag, or commit hash), you can select all projects with modifications since the corresponding commit.
This type of query uses similar logic as the rush change
command: Rush calculates the git diff
of the
current working directory versus the referenced commit, then computes a list of affected file paths.
These file paths are then matched with project folders from your rush.json workspace: In this way,
the git:
selector identifies the set of Rush projects with at least one modified file.
# Select projects whose source code has been changed according to Git,
# using the "main" branch as the basis for comparison.
# Build "--to" those projects and their dependencies.
rush build --to git:origin/main
# Select projects whose source code has been changed since
# the Git tag named "release/v3.0.0".
# List the downstream projects that would be "impacted by" these changes.
rush list --impacted-by git:release/v3.0.0
Subspace members: subspace:
The subspaces feature enables Rush projects to be grouped into subspaces that install using their own PNPM lockfile. The subspace:
selector matches all projects belonging to a given subspace.
Example:
# Build all projects belonging to the "install-test" subspace, as well
# as their dependencies:
rush build --to subspace:install-test
Tagged projects: tag:
Rush project tags enable you to define arbitrary collections of projects,
which can then be referenced using the tag:
selector.
Examples:
# Build all projects that were tagged with the "shipping" project tag.
rush build --to tag:shipping
# Print a report showing the set of projects
# that have the "frontend-team-libs" project tag.
rush list --only tag:frontend-team-libs --detailed
Combining parameters
- You can combine any of the selection parameters on a single command line. The result is always the union of each individual selection.
- The same parameter can be specified multiple times. For example:
rush build --only A --only B --only C
will selectA
,B
, andC
- Note that Rush does not provide any parameter that would reduce the selection. This is an intentional design choice; in #1241 we'll implement personal tags for building up more complex selections.)
Here's a more complex combined command-line:
rush build --only A --impacted-by-except B --to F
The projects selected by this example are A
, C
, D
, E
, and F
: