This page describes the use_execroot_entry_point option on js_run_binary
and provides guidance on when to use each value.
When a js_binary is used as a tool in js_run_binary, Bazel runs it as a
build action on the exec platform. The execroot is the root of the build
sandbox; beneath it sits bazel-out/, which contains output directories for
both the exec and target configurations. The tool's sources can therefore appear
in up to three places:
- Exec-platform bin (
bazel-out/<exec-cfg>/bin/): where build artifacts for the exec platform land. - Runfiles tree (
bazel-out/<exec-cfg>/bin/path/to/my_binary.runfiles/): where the tool's runtime dependencies (includingnode_modules) are symlinked and made available to the build action. - Target-platform bin (
bazel-out/<target-cfg>/bin/): where thesrcsof thejs_run_binaryaction land.
When Node.js resolves require(), it walks up the directory tree looking for
node_modules. If the working directory is somewhere that can see
node_modules from both the exec output tree and the runfiles tree, the same
package can resolve from two different paths, which can cause subtle bugs.
use_execroot_entry_point = True (the current default):
The tool's runfiles are hoisted into srcs, which causes them to be rebuilt in
the target configuration and land in the target-platform bin directory. The
entry point used is the one in that output tree (the "execroot entry point"),
rather than the copy inside the runfiles symlink tree. With everything
consolidated in bazel-out/<target-cfg>/bin/, Node.js sees a single
node_modules tree. This can be the right choice for some frameworks such as
Next.js, which expects inputs and outputs to be in the same directory tree.
The tradeoff is that if the exec platform differs from the target platform (for example, cross-compiling from macOS to Linux), target-platform artifacts such as native Node.js addons are rebuilt for the target and may fail to run on the exec platform.
use_execroot_entry_point = False:
The entry point used is the one from the runfiles tree. All code executed during
the build action runs from the runfiles tree, which avoids cross-platform
issues. However, you must ensure that any code executed during the build (for
example, JavaScript config files for tools like Webpack or Rspack) is a declared
dependency of the js_binary tool, not merely a source file passed to
js_run_binary. Config files in the js_run_binary's srcs will land in the
target-platform bin directory and will therefore not be visible to the tool's
runfiles resolution.
We recommend setting use_execroot_entry_point = False wherever possible and
ensuring that all code executed during the build is declared as a dependency of
the js_binary. The main exception is Next.js and similar frameworks that
expect inputs and outputs in the same directory tree or that execute
target-platform code during the build, in which case True is required.
To disable use_execroot_entry_point by default, pass the build flag:
--@aspect_rules_js//js:use_execroot_entry_point=False
Individual targets can still override the flag by explicitly setting
use_execroot_entry_point = True or use_execroot_entry_point = False.
In a future major version, we will likely disable the use_execroot_entry_point
behavior by default.