Skip to content

Latest commit

 

History

History
79 lines (64 loc) · 4.94 KB

js-rush-options.md

File metadata and controls

79 lines (64 loc) · 4.94 KB

Rush resolver options

Rush offers two alternatives for constructing the build graph.

Configuring rush-lib

The Rush resolver can use rush-lib to discover the project-to-project graph. If not specified, BuildXL tries to find rush in PATH and the instance of rush-lib that ships with Rush.

The version of this library matters for cache hits, since different versions might produce different graphs. Similarly to the environment, pinning the version is a good idea to keep things under control. It will also improve the chances of getting cache hits across builds:

config({
  resolvers: [
      {
        kind: "Rush",
        ...
        rushLibBaseLocation: d`${Environment.getDirectoryValue("RUSHTOOL_INSTALL_LOCATION")}/node_modules/@microsoft/rush/node_modules`,

      }
  ]
});

So assuming RUSHTOOL_INSTALL_LOCATION is an env var containing the directory where Rush is installed, here we point to the node_modules directory that contains rush-lib.

Configuring @rushstack/rush-build-graph-plugin

The @rushstack/rush-build-graph-plugin plugin produces a finer-grained build graph, where each node represents a script under a given project. Observe that the same level of granularity can be achieved with rush-lib, specifying the script-to-script dependencies in the BuildXL main configuration file. However, the main advantages of using the plugin are

  • The source of truth that defines the extent of the build comes entirely from Rush, making BuildXL and non-BuildXL builds equivalent.
  • It reduces the onboarding cost by removing the cognitive load and configuration requirements around defining script-to-script dependencies at the BuildXL configuration level.
  • It enables a finer-grained control over script dependencies, where JavaScript-specific optimizations that reflect in point scripts can be expressed and driven from Rush, a domain-specific JavaScript coordinator.

In order to use the plugin, a rush instance needs to be provided to BuildXL:

config({
  resolvers: [
      {
        kind: "Rush",
        ...
        rushLocation: f`${Environment.getDirectoryValue("RUSHTOOL_INSTALL_LOCATION")}/bin/rush`,
      }
  ]
});

Assuming RUSHTOOL_INSTALL_LOCATION is an env var containing the directory where Rush is installed, we point to the Rush binary. It is assumed @rushstack/rush-build-graph-plugin is installed on the provided Rush instance.

Equivalently to lage commands, execute in this case only takes script command names (or command groups), but without the option of establishing a dependency across them. This information is already part of what the plugin provides:

config({
  resolvers: [
      {
        kind: "Rush",
        ...
        rushLocation: f`${Environment.getDirectoryValue("RUSHTOOL_INSTALL_LOCATION")}/bin/rush`,
        execute: ["build", "test"],
      }
  ]
});

Here we are specifying build and test as a way to define the build extent, but there is no implicit dependency between these commands and the order is not important.

Improving perf with shrinkwrap-deps.json

Rush produces a project-level shrinkwrap file named shrinkwrap-deps.json. This file contains the transitive closure of all dependency names, including versions, for the corresponding project. This file can be used to track if any dependency changed, and therefore the associated project has to be re-run, instead of the real dependencies. The BuildXL Rush resolver exposes an option to do this:

config({
    resolvers: [
    {
        kind: "Rush",
        ...
         trackDependenciesWithShrinkwrapDepsFile: true,
    }]
});

When enabled, this option will make BuildXL ignore any changes in the project dependencies and instead use shrinkwrap-deps.json as a witness for that. The net effect is that BuildXL will need to track for changes a potentially much smaller set of files, improving cache lookups and post-processing times. Observe, however, this option opens the door to some level of unsafety since using shrinkwrap-deps.json will do the trick as long as it is up-to-date. If any package.json file is modified and rush update is not run, this file might not be appropriately updated and therefore package dependencies not properly reflected. Therefore, an underbuild is possible, where a true dependency that is not listed in shrinkwrap-deps.json changes. Therefore, the recommendation is to turn this option on for lab builds, where this type of prerequisites are usually met, but leave it off (the default) for local builds.