aspect_rules_jsAPI docs @3.0.0-rc6

@aspect_rules_js//contrib/nextjs:defs.bzl

Utilities for building Next.js applications with Bazel and rules_js.

All invocations of Next.js are done through a next_js_binary target passed into the macros.
This is normally generated once alongside the package.json containing the next dependency:

load("@npm//:next/package_json.bzl", next_bin = "bin")

next_bin.next_binary(
    name = "next_js_binary",
    visibility = ["//visibility:public"],
)

The next binary is then passed into the macros, for example:

nextjs_build(
    name = "next",
    config = "next.config.mjs",
    srcs = glob(["src/**"]),
    next_js_binary = "//:next_js_binary",
)

There are two sets of macros for building Next.js applications: standard and standalone.

Standard Build

  • nextjs(): wrap the build+dev+start targets
  • nextjs_build(): the Next.js build command
  • nextjs_dev(): the Next.js dev command
  • nextjs_start(): the Next.js start command,
    accepting a Next.js build artifact to start

Standalone Mode

For standalone applications:

  • nextjs_standalone_build(): the Next.js build command,
    configured for a standalone application within bazel
  • nextjs_standalone_server(): constructs a standalone Next.js server js_binary following the
    standalone directory structure guidelines

Functions & Macros

nextjs

Generates Next.js build, dev & start targets.

{name} - a Next.js production bundle
{name}.dev - a Next.js devserver
{name}.start - a Next.js prodserver

Use this macro in the BUILD file at the root of a next app where the next.config.mjs
file is located.

For example, a target such as //app:next in app/BUILD.bazel

next(
    name = "next",
    config = "next.config.mjs",
    srcs = glob(["src/**"]),
    data = [
        "//:node_modules/next",
        "//:node_modules/react-dom",
        "//:node_modules/react",
        "package.json",
    ],
    next_js_binary = "//:next_js_binary",
)

will create the targets:

//app:next
//app:next.dev
//app:next.start

To build the above next app, equivalent to running next build outside Bazel:

bazel build //app:next

To run the development server in watch mode with
ibazel, equivalent to running
next dev outside Bazel:

ibazel run //app:next.dev

To run the production server in watch mode with
ibazel, equivalent to running
next start outside Bazel:

ibazel run //app:next.start
Parameters
*name

the name of the build target

*srcs

Source files to include in build & dev targets.
Typically these are source files or transpiled source files in Next.js source folders
such as pages, public & styles.

*next_js_binary

The next js_binary target to use for running Next.js

Typically this is a js_binary target created using bin loaded from the package_json.bzl
file of the npm package.

See main docstring above for example usage.

config

the Next.js config file. Typically next.config.mjs.

Default: "next.config.mjs"
data

Data files to include in all targets.
These are typically npm packages required for the build & configuration files such as
package.json and next.config.js.

Default: []
serve_data

Data files to include in devserver targets

Default: []
kwargs

Other attributes passed to all targets such as tags.

nextjs_build

Build the Next.js production artifact.

See https://nextjs.org/docs/pages/api-reference/cli/next#build

Parameters
*name

the name of the build target

*config

the Next.js config file

*srcs

the sources to include in the build, including any transitive deps

*next_js_binary

The next js_binary target to use for running Next.js

Typically this is a js_binary target created using bin loaded from the package_json.bzl
file of the npm package.

See main docstring above for example usage.

data

the data files to include in the build

Default: []
kwargs

Other attributes passed to all targets such as tags, env

nextjs_start

Run the Next.js production server for an app.

See https://nextjs.org/docs/pages/api-reference/cli/next#next-start-options

Parameters
*name

the name of the build target

*config

the Next.js config file

*app

the pre-compiled Next.js application, typically the output of nextjs_build

*next_js_binary

The next js_binary target to use for running Next.js

Typically this is a js_binary target created using bin loaded from the package_json.bzl
file of the npm package.

See main docstring above for example usage.

data

additional server data

Default: []
kwargs

Other attributes passed to all targets such as tags, env

nextjs_dev
Parameters
*name

the name of the build target

*config

the Next.js config file

*srcs

the sources to include in the build, including any transitive deps

*data

additional devserver runtime data

*next_js_binary

The next js_binary target to use for running Next.js

Typically this is a js_binary target created using bin loaded from the package_json.bzl
file of the npm package.

See main docstring above for example usage.

kwargs

Other attributes passed to all targets such as tags, env

nextjs_standalone_build

Compile a standalone Next.js application.

See https://nextjs.org/docs/app/api-reference/config/next-config-js/output#automatically-copying-traced-files

NOTE: a next.config.mjs is generated, wrapping the passed config, to overcome Next.js limitation with bazel,
rules_js and pnpm (with hoist=false, as required by rules_js).

Due to the generated next.config.mjs file the nextjs_standalone_build(config) must have a unique name
or file path that does not conflict with standard Next.js config files.

Issues worked around by the generated config include:

Parameters
*name

the name of the build target

*config

the Next.js config file

*srcs

the sources to include in the build, including any transitive deps

*next_js_binary

the Next.js binary to use for building

data

the data files to include in the build

Default: []
kwargs

Other attributes passed to all targets such as tags, env

nextjs_standalone_server

Configures the output of a standalone Next.js application to be a standalone server binary.

See the Next.js standalone server documentation
for details on the standalone server directory structure.

This function is normally used in conjunction with nextjs_standalone_build to create a standalone
Next.js application. The standalone server is a js_binary target that can be run with bazel run
or deployed in a container image etc.

Parameters
*name

the name of the binary target

*app

the standalone app directory, typically the output of nextjs_standalone_build

pkg

the directory server.js is in within the standalone/ directory.

This is normally the application path relative to the pnpm-lock.yaml.

Default: native.package_name() (for a pnpm-lock.yaml in the root of the workspace)

Default: None
data

runtime data required to run the standalone server.

Normally requires [":node_modules/next", ":node_modules/react"] which are not included
in the Next.js standalone output.

Default: []
kwargs

additional js_binary attributes

@aspect_rules_js//js:defs.bzl

Rules for running JavaScript programs

Functions & Macros

js_binary
Parameters
kwargs
js_test
Parameters
kwargs
js_run_devserver

Runs a devserver via binary target or command.

A simple http-server, for example, can be setup as follows,

load("@aspect_rules_js//js:defs.bzl", "js_run_devserver")
load("@npm//:http-server/package_json.bzl", http_server_bin = "bin")

http_server_bin.http_server_binary(
    name = "http_server",
)

js_run_devserver(
    name = "serve",
    args = ["."],
    data = ["index.html"],
    tool = ":http_server",
)

A Next.js devserver can be setup as follows,

js_run_devserver(
    name = "dev",
    args = ["dev"],
    command = "./node_modules/.bin/next",
    data = [
        "next.config.js",
        "package.json",
        ":node_modules/next",
        ":node_modules/react",
        ":node_modules/react-dom",
        ":node_modules/typescript",
        "//pages",
        "//public",
        "//styles",
    ],
)

where the ./node_modules/.bin/next bin entry of Next.js is configured in
npm_translate_lock as such,

npm_translate_lock(
    name = "npm",
    bins = {
        # derived from "bin" attribute in node_modules/next/package.json
        "next": {
            "next": "./dist/bin/next",
        },
    },
    pnpm_lock = "//:pnpm-lock.yaml",
)

and run in watch mode using ibazel with
ibazel run //:dev.

The devserver specified by either tool or command is run in a custom sandbox that is more
compatible with devserver watch modes in Node.js tools such as Webpack and Next.js.

The custom sandbox is populated with the default outputs of all targets in data
as well as transitive sources & npm links.

As an optimization, package store files are explicitly excluded from the sandbox since the npm
links will point to the package store in the execroot and Node.js will follow those links as it
does within the execroot. As a result, rules_js npm package link targets such as
//:node_modules/next are handled efficiently. Since these targets are symlinks in the output
tree, they are recreated as symlinks in the custom sandbox and do not incur a full copy of the
underlying npm packages.

Supports running with ibazel.
Only data files that change on incremental builds are synchronized when running with ibazel.

Note that the use of alias targets is not supported by ibazel: https://github.com/bazelbuild/bazel-watcher/issues/100

Parameters
*name

A unique name for this target.

tool

The devserver binary target to run.

Only one of command or tool may be specified.

Default: None
command

The devserver command to run.

For example, this could be the bin entry of an npm package that is included
in data such as ./node_modules/.bin/next.

Using the bin entry of next, for example, resolves issues with Next.js and React
being found in multiple node_modules trees when next is run as an encapsulated
js_binary tool.

Only one of command or tool may be specified.

Default: None
grant_sandbox_write_permissions

If set, write permissions is set on all files copied to the custom sandbox.

This can be useful to support some devservers such as Next.js which may, under some
circumstances, try to modify files when running.

See https://github.com/aspect-build/rules_js/issues/935 for more context.

Default: False
use_execroot_entry_point

Use the entry_point script of the js_binary tool that is in the execroot output tree
instead of the copy that is in runfiles.

Using the entry point script that is in the execroot output tree means that there will be no conflicting
runfiles node_modules in the node_modules resolution path which can confuse npm packages such as next and
react that don't like being resolved in multiple node_modules trees. This more closely emulates the
environment that tools such as Next.js see when they are run outside of Bazel.

When True, the js_binary tool must have copy_data_to_bin set to True (the default) so that all data files
needed by the binary are available in the execroot output tree. This requirement can be turned off with by
setting allow_execroot_entry_point_with_no_copy_data_to_bin to True.

Default: True
allow_execroot_entry_point_with_no_copy_data_to_bin

Turn off validation that the js_binary tool
has copy_data_to_bin set to True when use_execroot_entry_point is set to True.

See use_execroot_entry_point doc for more info.

Default: False
kwargs

All other args from js_binary except for entry_point which is set implicitly.

entry_point is set implicitly by js_run_devserver and cannot be overridden.

See https://docs.aspect.build/rules/aspect_rules_js/docs/js_binary

js_run_binary

Wrapper around @bazel_lib run_binary that adds convenience attributes for using a js_binary tool.

This rule does not require Bash native.genrule.

The following environment variables are made available to the Node.js runtime based on available Bazel Make variables:

  • BAZEL_BINDIR: the bazel bin directory; equivalent to the $(BINDIR) Make variable of the js_run_binary target
  • BAZEL_COMPILATION_MODE: One of fastbuild, dbg, or opt as set by --compilation_mode; equivalent to $(COMPILATION_MODE) Make variable of the js_run_binary target
  • BAZEL_TARGET_CPU: the target cpu architecture; equivalent to $(TARGET_CPU) Make variable of the js_run_binary target

The following environment variables are made available to the Node.js runtime based on the rule context:

  • BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to ctx.build_file_path of the js_run_binary target's rule context
  • BAZEL_PACKAGE: the package of the bazel target being run; equivalent to ctx.label.package of the js_run_binary target's rule context
  • BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of ctx.label of the js_run_binary target's rule context
  • BAZEL_TARGET: the name of the bazel target being run; equivalent to ctx.label.name of the js_run_binary target's rule context
  • BAZEL_WORKSPACE: the bazel repository name; equivalent to ctx.workspace_name of the js_run_binary target's rule context
Parameters
*name

Target name

*tool

The tool to run in the action.

Should be a js_binary rule. Use Aspect bazel-lib's run_binary
(https://github.com/bazel-contrib/bazel-lib/blob/main/lib/run_binary.bzl)
for other *_binary rule types.

env

Environment variables of the action.

Subject to $(location) and make variable expansion.

Default: {}
srcs

Additional inputs of the action.

These labels are available for $(location) expansion in args and env.

Default: []
outs

Output files generated by the action.

These labels are available for $(location) expansion in args and env.

Default: []
out_dirs

Output directories generated by the action.

These labels are not available for $(location) expansion in args and env since
they are not pre-declared labels created via attr.output_list(). Output directories are
declared instead by ctx.actions.declare_directory.

Default: []
args

Command line arguments of the binary.

Subject to $(location) and make variable expansion.

Default: []
chdir

Working directory to run the build action in.

This overrides the chdir value if set on the js_binary tool target.

By default, js_binary tools run in the root of the output tree. For more context on why, please read the
aspect_rules_js README
https://github.com/aspect-build/rules_js/tree/dbb5af0d2a9a2bb50e4cf4a96dbc582b27567155#running-nodejs-programs.

To run in the directory containing the js_run_binary in the output tree, use
chdir = package_name() (or if you're in a macro, use native.package_name()).

WARNING: this will affect other paths passed to the program, either as arguments or in configuration files,
which are workspace-relative.

You may need ../../ segments to re-relativize such paths to the new working directory.

Default: None
stdout

Output file to capture the stdout of the binary.

This can later be used as an input to another target subject to the same semantics as outs.

If the binary creates outputs and these are declared, they must still be created.

Default: None
stderr

Output file to capture the stderr of the binary to.

This can later be used as an input to another target subject to the same semantics as outs.

If the binary creates outputs and these are declared, they must still be created.

Default: None
exit_code_out

Output file to capture the exit code of the binary to.

This can later be used as an input to another target subject to the same semantics as outs. Note that
setting this will force the binary to exit 0.

If the binary creates outputs and these are declared, they must still be created.

Default: None
silent_on_success

produce no output on stdout nor stderr when program exits with status code 0.

This makes node binaries match the expected bazel paradigm.

Default: True
use_execroot_entry_point

Use the entry_point script of the js_binary tool that is in the execroot output tree
instead of the copy that is in runfiles.

Runfiles of tool are all hoisted to srcs of the underlying run_binary so they are included as execroot
inputs to the action.

Using the entry point script that is in the execroot output tree means that there will be no conflicting
runfiles node_modules in the node_modules resolution path which can confuse npm packages such as next and
react that don't like being resolved in multiple node_modules trees. This more closely emulates the
environment that tools such as Next.js see when they are run outside of Bazel.

When True, the js_binary tool must have copy_data_to_bin set to True (the default) so that all data files
needed by the binary are available in the execroot output tree. This requirement can be turned off with by
setting allow_execroot_entry_point_with_no_copy_data_to_bin to True.

Default: True
copy_srcs_to_bin

When True, all srcs files are copied to the output tree that are not already there.

Default: True
include_sources

see js_info_files documentation

Default: True
include_types

see js_info_files documentation

Default: False
include_transitive_sources

see js_info_files documentation

Default: True
include_transitive_types

see js_info_files documentation

Default: False
include_npm_sources

see js_info_files documentation

Default: True
log_level

Set the logging level of the js_binary tool.

This overrides the log level set on the js_binary tool target.

Default: None
mnemonic

A one-word description of the action, for example, CppCompile or GoLink.

Default: "JsRunBinary"
progress_message

Progress message to show to the user during the build, for example,
"Compiling foo.cc to create foo.o". The message may contain %{label}, %{input}, or
%{output} patterns, which are substituted with label string, first input, or output's
path, respectively. Prefer to use patterns instead of static strings, because the former
are more efficient.

Default: None
execution_requirements

Information for scheduling the action.

For example,

execution_requirements = {
    "no-cache": "1",
},

See https://docs.bazel.build/versions/main/be/common-definitions.html#common.tags for useful keys.

Default: None
stamp

Whether to include build status files as inputs to the tool. Possible values:

  • stamp = 0 (default): Never include build status files as inputs to the tool.
    This gives good build result caching.
    Most tools don't use the status files, so including them in --stamp builds makes those
    builds have many needless cache misses.
    (Note: this default is different from most rules with an integer-typed stamp attribute.)
  • stamp = 1: Always include build status files as inputs to the tool, even in
    --nostamp builds.
    This setting should be avoided, since it is non-deterministic.
    It potentially causes remote cache misses for the target and
    any downstream actions that depend on the result.
  • stamp = -1: Inclusion of build status files as inputs is controlled by the
    --[no]stamp flag.
    Stamped targets are not rebuilt unless their dependencies change.

Default value is 0 since the majority of js_run_binary targets in a build graph typically do not use build
status files and including them for all js_run_binary actions whenever --stamp is set would result in
invalidating the entire graph and would prevent cache hits. Stamping is typically done in terminal targets
when building release artifacts and stamp should typically be set explicitly in these targets to -1 so it
is enabled when the --stamp flag is set.

When stamping is enabled, an additional two environment variables will be set for the action:
- BAZEL_STABLE_STATUS_FILE
- BAZEL_VOLATILE_STATUS_FILE

These files can be read and parsed by the action, for example to pass some values to a bundler.

Default: 0
patch_node_fs

Patch the to Node.js fs API (https://nodejs.org/api/fs.html) for this node program
to prevent the program from following symlinks out of the execroot, runfiles and the sandbox.

When enabled, js_binary patches the Node.js sync and async fs API functions lstat,
readlink, realpath, readdir and opendir so that the node program being
run cannot resolve symlinks out of the execroot and the runfiles tree. When in the sandbox,
these patches prevent the program being run from resolving symlinks out of the sandbox.

When disabled, node programs can leave the execroot, runfiles and sandbox by following symlinks
which can lead to non-hermetic behavior.

Default: True
allow_execroot_entry_point_with_no_copy_data_to_bin

Turn off validation that the js_binary tool
has copy_data_to_bin set to True when use_execroot_entry_point is set to True.

See use_execroot_entry_point doc for more info.

Default: False
use_default_shell_env

Passed to the underlying ctx.actions.run.

May introduce non-determinism when True; use with care!
See e.g. https://github.com/bazelbuild/bazel/issues/4912

Refer to https://bazel.build/rules/lib/builtins/actions#run for more details.

Default: False
kwargs

Additional arguments

Rules

js_library

A library of JavaScript sources. Provides JsInfo, the primary provider used in rules_js
and derivative rule sets.

Declaration files are handled separately from sources since they are generally not needed at
runtime and build rules, such as ts_project, are optimal in their build graph if they only depend
on types from deps since these they don't need the JavaScript source files from deps to
typecheck.

Linked npm dependences are also handled separately from sources since not all rules require them and it
is optimal for these rules to not depend on them in the build graph.

NB: js_library copies all source files to the output tree before providing them in JsInfo. See
https://github.com/aspect-build/rules_js/tree/dbb5af0d2a9a2bb50e4cf4a96dbc582b27567155/docs#javascript
for more context on why we do this.

AttributeTypeDescription
*namename

A unique name for this target.

srcslist of labels

Source files that are included in this library.

This includes all your checked-in code and any generated source files.

The transitive npm dependencies, transitive sources & runfiles of targets in the srcs attribute are added to the
runfiles of this target. They should appear in the '*.runfiles' area of any executable which is output by or has a
runtime dependency on this target.

Source files that are JSON files, declaration files or directory artifacts will be automatically provided as
"types" available to downstream rules for type checking. To explicitly provide source files as "types"
available to downstream rules for type checking that do not match these criteria, move those files to the types
attribute instead.

Default: []
typeslist of labels

Same as srcs except all files are also provided as "types" available to downstream rules for type checking.

For example, a js_library with only .js files that are intended to be imported as .js files by downstream type checking
rules such as ts_project would list those files in types:

js_library(
    name = "js_lib",
    types = ["index.js"],
)
Default: []
depslist of labels

Dependencies of this target.

This may include other js_library targets or other targets that provide JsInfo

The transitive npm dependencies, transitive sources & runfiles of targets in the deps attribute are added to the
runfiles of this target. They should appear in the '*.runfiles' area of any executable which is output by or has a
runtime dependency on this target.

If this list contains linked npm packages, npm package store targets or other targets that provide
JsInfo, NpmPackageStoreInfo providers are gathered from JsInfo. This is done directly from
the npm_package_store_infos field of these. For linked npm package targets, the underlying
npm_package_store target(s) that back the links are used. Gathered NpmPackageStoreInfo
providers are propagated to the direct dependencies of downstream linked targets.

NB: Linked npm package targets that are "dev" dependencies do not forward their underlying
npm_package_store target(s) through npm_package_store_infos and will therefore not be
propagated to the direct dependencies of downstream linked targets. npm packages
that come in from npm_translate_lock are considered "dev" dependencies if they are have
dev: true set in the pnpm lock file. This should be all packages that are only listed as
"devDependencies" in all package.json files within the pnpm workspace. This behavior is
intentional to mimic how devDependencies work in published npm packages.

Default: []
datalist of labels

Runtime dependencies to include in binaries/tests that depend on this target.

The transitive npm dependencies, transitive sources, default outputs and runfiles of targets in the data attribute
are added to the runfiles of this target. They should appear in the '*.runfiles' area of any executable which has
a runtime dependency on this target.

If this list contains linked npm packages, npm package store targets or other targets that provide
JsInfo, NpmPackageStoreInfo providers are gathered from JsInfo. This is done directly from
the npm_package_store_infos field of these. For linked npm package targets, the underlying
npm_package_store target(s) that back the links are used. Gathered NpmPackageStoreInfo
providers are propagated to the direct dependencies of downstream linked targets.

NB: Linked npm package targets that are "dev" dependencies do not forward their underlying
npm_package_store target(s) through npm_package_store_infos and will therefore not be
propagated to the direct dependencies of downstream linked targets. npm packages
that come in from npm_translate_lock are considered "dev" dependencies if they are have
dev: true set in the pnpm lock file. This should be all packages that are only listed as
"devDependencies" in all package.json files within the pnpm workspace. This behavior is
intentional to mimic how devDependencies work in published npm packages.

Default: []
no_copy_to_binlist of labels

List of files to not copy to the Bazel output tree when copy_data_to_bin is True.

This is useful for exceptional cases where a copy_to_bin is not possible or not suitable for an input
file such as a file in an external repository. In most cases, this option is not needed.
See copy_data_to_bin docstring for more info.

Default: []
copy_data_to_binboolean

When True, data files are copied to the Bazel output tree before being passed as inputs to runfiles.

Default: True
js_info_files

Gathers files from the JsInfo providers from targets in srcs and provides them as default outputs.

This helper rule is used by the js_run_binary macro.

AttributeTypeDescription
*namename

A unique name for this target.

srcslist of labels

List of targets to gather files from.

Default: []
include_sourcesboolean

When True, sources from JsInfo providers in srcs targets are included in the default outputs of the target.

Default: True
include_transitive_sourcesboolean

When True, transitive_sources from JsInfo providers in srcs targets are included in the default outputs of the target.

Default: True
include_typesboolean

When True, types from JsInfo providers in srcs targets are included in the default outputs of the target.

Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip
time due to having to generate typings on source file changes.

NB: These are types from direct srcs dependencies only. You may also need to set include_transitive_types to True.

Default: False
include_transitive_typesboolean

When True, transitive_types from JsInfo providers in srcs targets are included in the default outputs of the target.

Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip
time due to having to generate typings on source file changes.

Default: False
include_npm_sourcesboolean

When True, files in npm_sources from JsInfo providers in srcs targets are included in the default outputs of the target.

transitive_files from NpmPackageStoreInfo providers in srcs targets are also included in the default outputs of the target.

Default: True
js_image_layer

Create container image layers from js_binary targets.

By design, js_image_layer doesn't have any preference over which rule assembles the container image.
This means the downstream rule (oci_image from rules_oci
or container_image from rules_docker) must
set a proper workdir and cmd to for the container work.

A proper cmd usually looks like /[ js_image_layer 'root' ]/[ package name of js_image_layer 'binary' target ]/[ name of js_image_layer 'binary' target ],
unless you have a custom launcher script that invokes the entry_point of the js_binary in a different path.

On the other hand, workdir has to be set to the "runfiles tree root" which would be exactly cmd but with .runfiles/[ name of the workspace ] suffix.
When using bzlmod then name of the local workspace is always _main. If workdir is not set correctly, some attributes such as chdir might not work properly.

js_image_layer creates up to 5 layers depending on what files are included in the runfiles of the provided
binary target.

  1. node layer contains the Node.js toolchain
  2. package_store_3p layer contains all 3p npm deps in the node_modules/.aspect_rules_js package store
  3. package_store_1p layer contains all 1p npm deps in the node_modules/.aspect_rules_js package store
  4. node_modules layer contains all node_modules/* symlinks which point into the package store
  5. app layer contains all files that don't fall into any of the above layers

If no files are found in the runfiles of the binary target for one of the layers above, that
layer is not generated. All generated layer tarballs are provided as DefaultInfo files.

The rules_js node_modules/.aspect_rules_js package store follows the same pattern as the pnpm
node_modules/.pnpm virtual store. For more information see https://pnpm.io/symlinked-node-modules-structure.

js_image_layer also provides an OutputGroupInfo with outputs for each of the layers above which
can be used to reference an individual layer with using filegroup with output_group. For example,

js_image_layer( name = "layers", binary = ":bin", root = "/app", ) filegroup( name = "app_tar", srcs = [":layers"], output_group = "app", )

WARNING: The structure of the generated layers are not subject to semver guarantees and may change without a notice.
However, it is guaranteed to work when all generated layers are provided together in the order specified above.

js_image_layer supports transitioning to specific platform to allow building multi-platform container images.

A partial example using rules_oci with transition to linux/amd64 platform.

load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_image_layer") load("@rules_oci//oci:defs.bzl", "oci_image") js_binary( name = "bin", entry_point = "main.js", ) platform( name = "amd64_linux", constraint_values = [ "@platforms//os:linux", "@platforms//cpu:x86_64", ], ) js_image_layer( name = "layers", binary = ":bin", platform = ":amd64_linux", root = "/app", ) oci_image( name = "image", cmd = ["/app/bin"], entrypoint = ["bash"], tars = [ ":layers" ], workdir = "/app/bin.runfiles/_main", )

A partial example using rules_oci to create multi-platform images.

load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_image_layer") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") js_binary( name = "bin", entry_point = "main.js", ) [ platform( name = "linux_{}".format(arch), constraint_values = [ "@platforms//os:linux", "@platforms//cpu:{}".format(arch if arch != "amd64" else "x86_64"), ], ) js_image_layer( name = "{}_layers".format(arch), binary = ":bin", platform = ":linux_{arch}", root = "/app", ) oci_image( name = "{}_image".format(arch), cmd = ["/app/bin"], entrypoint = ["bash"], tars = [ ":{}_layers".format(arch) ], workdir = "/app/bin.runfiles/_main", ) for arch in ["amd64", "arm64"] ] oci_image_index( name = "image", images = [ ":arm64_image", ":amd64_image" ] )

For better performance, it is recommended to split the large parts of a js_binary to have a separate layer.

The matching order for layer groups is as follows:

  1. layer_groups are checked in order first
  2. If no match is found for layer_groups, the default layer groups are checked.
  3. Any remaining files are placed into the app layer.

The default layer groups are as follows and always created.

{
    "node": "/js/private/node-patches/|/bin/nodejs/",
    "package_store_1p": "\.aspect_rules_js/.*@0\.0\.0/node_modules",
    "package_store_3p": "\.aspect_rules_js/.*/node_modules",
    "node_modules": "/node_modules/",
    "app": "", # empty means just match anything.
}
AttributeTypeDescription
*namename

A unique name for this target.

*binarylabel

Label to an js_binary target

rootstring

Path where the files from js_binary will reside in. eg: /apps/app1 or /app

Default: ""
ownerstring

Owner of the entries, in GID:UID format. By default 0:0 (root, root) is used.

Default: "0:0"
directory_modestring

Mode of the directories, in octal format. By default 0755 is used.

Default: "0755"
file_modestring

Mode of the files, in octal format. By default 0555 is used.

Default: "0555"
compressionstring

Compression algorithm. See https://github.com/bazel-contrib/bazel-lib/blob/bdc6ade0ba1ebe88d822bcdf4d4aaa2ce7e2cd37/lib/private/tar.bzl#L29-L39

Default: "gzip"
platformlabel

Platform to transition.

Default: None
preserve_symlinksstring

Preserve symlinks for entries matching the pattern.
By default symlinks within the node_modules is preserved.

Default: ".*/node_modules/.*"
layer_groupsdictionary: String → String

Layer groups to create.
These are utilized to categorize files into distinct layers, determined by their respective paths.
The expected format for each entry is "<key>": "<value>", where <key> MUST be a valid Bazel and
JavaScript identifier (alphanumeric characters), and <value> MAY be either an empty string (signifying a universal match)
or a valid regular expression.

Default: {}

@aspect_rules_js//js:proto.bzl

EXPERIMENTAL: Protobuf and gRPC support for JavaScript and TypeScript.

This API is subject to breaking changes outside our usual semver policy.
In a future release of rules_js this should become stable.

Typical setup

  1. Choose any code generator plugin for protoc.
    In this example we'll show @bufbuild/protoc-gen-es that produces both message marshaling and service stubs for JavaScript and TypeScript.
    It should be added as a devDependency in your package.json, typically under a /tools directory.
    The generator is expected to produce .js and .d.ts files for each .proto file.
  2. Declare a binary target that runs the generator, typically using its package_json.bzl entry point, for example:
load("@npm//tools:@bufbuild/protoc-gen-es/package_json.bzl", gen_es = "bin") gen_es.protoc_gen_es_binary( name = "protoc_gen_es", )
  1. Define a js_proto_toolchain that uses the plugin. See the rule documentation below.
  2. Update MODULE.bazel to register it, typically with a simple statement like register_toolchains("//tools/toolchains:all")

Usage

Just write proto_library targets as usual, or have Gazelle generate them.
Then reference them anywhere a js_library could appear, for example:

load("@aspect_rules_js//js:defs.bzl", "js_library") load("@protobuf//bazel:proto_library.bzl", "proto_library") proto_library( name = "eliza_proto", srcs = ["eliza.proto"], ) js_library( name = "proto", srcs = ["package.json"], deps = [":eliza_proto"], )

The generator you setup earlier will be invoked automatically as an action to generate the .js and .d.ts files.

Functions & Macros

js_proto_toolchain

Define a proto_lang_toolchain that uses the plugin.

Example:

js_proto_toolchain( name = "gen_es_protoc_plugin", plugin_bin = ":protoc_gen_es", plugin_name = "es", # See https://github.com/bufbuild/protobuf-es/tree/main/packages/protoc-gen-es#plugin-options plugin_options = [ "keep_empty_files=true", "target=js+dts", "import_extension=js", ], runtime = "//:node_modules/@bufbuild/protobuf", )
Parameters
*name

The name of the toolchain. A target named [name]_toolchain is also created, which is the one to be used in register_toolchains.

*plugin_name

The NAME of the plugin program, used in command-line flags to protoc, as follows:

protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR

See https://protobuf.dev/reference/cpp/api-docs/google.protobuf.compiler.plugin

*plugin_options

(List of strings) Command line flags used to invoke the plugin, based on documentation for the generator.

For example, for @bufbuild/protoc-gen-es, reference the documentation at
https://github.com/bufbuild/protobuf-es/tree/main/packages/protoc-gen-es#plugin-options
to arrive at a value like ["import_extension=js"]

*plugin_bin

The plugin to use. This should be a label of a binary target that you declared in step 2 above.

*runtime

The runtime to use, which is imported by the generated code. For example, "//:node_modules/@bufbuild/protobuf".

Note that node module resolution requires the runtime to be in a parent folder of any package containing generated code.

kwargs

Additional arguments to pass to the proto_lang_toolchain rule.

@aspect_rules_js//npm:defs.bzl

Rules for fetching and linking npm dependencies and packaging and linking first-party deps

Functions & Macros

npm_package

A macro that packages sources into a directory (a tree artifact) and provides an NpmPackageInfo.

This target can be used as the src attribute to npm_link_package.

With publishable = True the macro also produces a target [name].publish, that can be run to publish to an npm registry.
Under the hood, this target runs npm publish. You can pass arguments to npm by escaping them from Bazel using a double-hyphen,
for example: bazel run //path/to:my_package.publish -- --tag=next

Files and directories can be arranged as needed in the output directory using
the root_paths, include_srcs_patterns, exclude_srcs_patterns and replace_prefixes attributes.

Filters and transformations are applied in the following order:

  1. include_external_repositories

  2. include_srcs_packages

  3. exclude_srcs_packages

  4. root_paths

  5. include_srcs_patterns

  6. exclude_srcs_patterns

  7. replace_prefixes

For more information on each filters / transformations applied, see
the documentation for the specific filter / transformation attribute.

Glob patterns are supported. Standard wildcards (globbing patterns) plus the ** doublestar (aka. super-asterisk)
are supported with the underlying globbing library, https://github.com/bmatcuk/doublestar. This is the same
globbing library used by gazelle. See https://github.com/bmatcuk/doublestar#patterns
for more information on supported globbing patterns.

npm_package makes use of copy_to_directory
(https://docs.aspect.build/rules/bazel_lib/docs/copy_to_directory) under the hood,
adopting its API and its copy action using composition. However, unlike copy_to_directory,
npm_package includes direct and transitive sources and types files from JsInfo providers in srcs
by default. The behavior of including sources and types from JsInfo can be configured
using the include_sources, include_transitive_sources, include_types, include_transitive_types.

The two include*_types options may cause type-check actions to run, which slows down your
development round-trip.

As of rules_js 2.0, the recommended solution for avoiding eager type-checking when linking
1p deps is to link js_library or any JsInfo producing targets directly without the
indirection of going through an npm_package target (see https://github.com/aspect-build/rules_js/pull/1646
for more details).

npm_package can also include npm packages sources and default runfiles from srcs which copy_to_directory does not.
These behaviors can be configured with the include_npm_sources and include_runfiles attributes
respectively.

The default include_srcs_packages, [".", "./**"], prevents files from outside of the target's
package and subpackages from being included.

The default exclude_srcs_patterns, of ["node_modules/**", "**/node_modules/**"], prevents
node_modules files from being included.

To stamp the current git tag as the "version" in the package.json file, see
stamped_package_json

Parameters
*name

Unique name for this target.

srcs

Files and/or directories or targets that provide DirectoryPathInfo to copy into the output directory.

Default: []
data

Runtime / linktime npm dependencies of this npm package.

NpmPackageStoreInfo providers are gathered from JsInfo of the targets specified. Targets can be linked npm
packages, npm package store targets or other targets that provide JsInfo. This is done directly from the
npm_package_store_infos field of these. For linked npm package targets, the underlying npm_package_store
target(s) that back the links are used.

Gathered NpmPackageStoreInfo providers are used downstream as direct dependencies of this npm package when
linking with npm_link_package.

Default: []
args

Arguments that are passed down to <name>.publish target and npm publish command.

Default: []
out

Path of the output directory, relative to this package.

Default: None
package

The package name. If set, should match the name field in the package.json file for this package.

If set, the package name set here will be used for linking if a npm_link_package does not specify a package name. A
npm_link_package that specifies a package name will override the value here when linking.

If unset, a npm_link_package that references this npm_package must define the package name for linking.

Default: ""
version

The package version. If set, should match the version field in the package.json file for this package.

If set, a npm_link_package may omit the package version and the package version set here will be used for linking. A
npm_link_package that specifies a package version will override the value here when linking.

If unset, a npm_link_package that references this npm_package must define the package version for linking.

Default: "0.0.0"
root_paths

List of paths (with glob support) that are roots in the output directory.

If any parent directory of a file being copied matches one of the root paths
patterns specified, the output directory path will be the path relative to the root path
instead of the path relative to the file's workspace. If there are multiple
root paths that match, the longest match wins.

Matching is done on the parent directory of the output file path so a trailing '**' glob pattern
will match only up to the last path segment of the dirname and will not include the basename.
Only complete path segments are matched. Partial matches on the last segment of the root path
are ignored.

Forward slashes (/) should be used as path separators.

A "." value expands to the target's package path (ctx.label.package).

Defaults to ["."] which results in the output directory path of files in the
target's package and sub-packages are relative to the target's package and
files outside of that retain their full workspace relative paths.

Globs are supported (see rule docstring above).

Default: ["."]
include_external_repositories

List of external repository names (with glob support) to include in the output directory.

Files from external repositories are only copied into the output directory if
the external repository they come from matches one of the external repository patterns
specified.

When copied from an external repository, the file path in the output directory
defaults to the file's path within the external repository. The external repository
name is not included in that path.

For example, the following copies @external_repo//path/to:file to
path/to/file within the output directory.

npm_package(
    name = "dir",
    include_external_repositories = ["external_*"],
    srcs = ["@external_repo//path/to:file"],
)

Files that come from matching external are subject to subsequent filters and
transformations to determine if they are copied and what their path in the output
directory will be. The external repository name of the file from an external
repository is not included in the output directory path and is considered in subsequent
filters and transformations.

Globs are supported (see rule docstring above).

Default: []
include_srcs_packages

List of Bazel packages (with glob support) to include in output directory.

Files in srcs are only copied to the output directory if
the Bazel package of the file matches one of the patterns specified.

Forward slashes (/) should be used as path separators. A first character of "."
will be replaced by the target's package path.

Defaults to ["./**"] which includes sources target's package and subpackages.

Files that have matching Bazel packages are subject to subsequent filters and
transformations to determine if they are copied and what their path in the output
directory will be.

Globs are supported (see rule docstring above).

Default: ["./**"]
exclude_srcs_packages

List of Bazel packages (with glob support) to exclude from output directory.

Files in srcs are not copied to the output directory if
the Bazel package of the file matches one of the patterns specified.

Forward slashes (/) should be used as path separators. A first character of "."
will be replaced by the target's package path.

Defaults to ["/node_modules/"] which excludes all node_modules folders
from the output directory.

Files that do not have matching Bazel packages are subject to subsequent
filters and transformations to determine if they are copied and what their path in the output
directory will be.

Globs are supported (see rule docstring above).

Default: []
include_srcs_patterns

List of paths (with glob support) to include in output directory.

Files in srcs are only copied to the output directory if their output
directory path, after applying root_paths, matches one of the patterns specified.

Forward slashes (/) should be used as path separators.

Defaults to ["**"] which includes all sources.

Files that have matching output directory paths are subject to subsequent
filters and transformations to determine if they are copied and what their path in the output
directory will be.

Globs are supported (see rule docstring above).

Default: ["**"]
exclude_srcs_patterns

List of paths (with glob support) to exclude from output directory.

Files in srcs are not copied to the output directory if their output
directory path, after applying root_paths, matches one of the patterns specified.

Forward slashes (/) should be used as path separators.

Files that do not have matching output directory paths are subject to subsequent
filters and transformations to determine if they are copied and what their path in the output
directory will be.

Globs are supported (see rule docstring above).

Default: ["**/node_modules/**"]
replace_prefixes

Map of paths prefixes (with glob support) to replace in the output directory path when copying files.

If the output directory path for a file starts with or fully matches a
a key in the dict then the matching portion of the output directory path is
replaced with the dict value for that key. The final path segment
matched can be a partial match of that segment and only the matching portion will
be replaced. If there are multiple keys that match, the longest match wins.

Forward slashes (/) should be used as path separators.

Replace prefix transformation are the final step in the list of filters and transformations.
The final output path of a file being copied into the output directory
is determined at this step.

Globs are supported (see rule docstring above).

Default: {}
allow_overwrites

If True, allow files to be overwritten if the same output file is copied to twice.

The order of srcs matters as the last copy of a particular file will win when overwriting.
Performance of npm_package will be slightly degraded when allow_overwrites is True
since copies cannot be parallelized out as they are calculated. Instead all copy paths
must be calculated before any copies can be started.

Default: False
include_sources

When True, sources from JsInfo providers in srcs targets are included in the list of available files to copy.

Default: True
include_types

When True, types from JsInfo providers in srcs targets are included in the list of available files to copy.

Default: True
include_transitive_sources

When True, transitive_sources from JsInfo providers in srcs targets are included in the list of available files to copy.

Default: True
include_transitive_types

When True, transitive_types from JsInfo providers in srcs targets are included in the list of available files to copy.

Default: True
include_npm_sources

When True, npm_sources from JsInfo providers in srcs targets are included in the list of available files to copy.

Default: False
include_runfiles

When True, default runfiles from srcs targets are included in the list of available files to copy.

This may be needed in a few cases:

  • to work-around issues with rules that don't provide everything needed in sources, transitive_sources, types & transitive_types
  • to depend on the runfiles targets that don't use JsInfo

NB: The default value will be flipped to False in the next major release as runfiles are not needed in the general case
and adding them to the list of files available to copy can add noticeable overhead to the analysis phase in a large
repository with many npm_package targets.

Default: False
hardlink

Controls when to use hardlinks to files instead of making copies.

Creating hardlinks is much faster than making copies of files with the caveat that
hardlinks share file permissions with their source.

Since Bazel removes write permissions on files in the output tree after an action completes,
hardlinks to source files are not recommended since write permissions will be inadvertently
removed from sources files.

  • auto: hardlinks are used for generated files already in the output tree
  • off: all files are copied
  • on: hardlinks are used for all files (not recommended)
Default: "auto"
publishable

When True, enable generation of {name}.publish target

Default: False
verbose

If true, prints out verbose logs to stdout

Default: False
kwargs

Additional attributes such as tags and visibility

stamped_package_json

Convenience wrapper to set the "version" property in package.json with the git tag.

In unstamped builds (typically those without --stamp) the version will be set to 0.0.0.
This ensures that actions which use the package.json file can get cache hits.

For more information on stamping, read https://docs.aspect.build/rules/bazel_lib/docs/stamping.

Parameters
*name

name of the resulting jq target, must be "package"

*stamp_var

a key from the bazel-out/stable-status.txt or bazel-out/volatile-status.txt files

kwargs

additional attributes passed to the jq rule, see https://docs.aspect.build/rules/bazel_lib/docs/jq

@aspect_rules_js//npm:extensions.bzl

Setup steps, or extensions for pnpm.

These are used in MODULE.bazel files to pin tooling versions, for example assuming

  • the desired version of Node.js is specified in a .nvmrc file
  • the desired version of pnpm is specified in the package.json#packageManager field
  • package manager preferences (especially hoist=false) is in .npmrc
  • pnpm dependencies were resolved and locked using pnpm-lock.yaml

then the following MODULE.bazel file can be used:

node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node") node.toolchain(node_version_from_nvmrc = "//:.nvmrc") use_repo(node, "nodejs_toolchains") pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm") use_repo(pnpm, "pnpm") pnpm.pnpm(pnpm_version_from = "//:package.json") npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm") npm.npm_translate_lock( name = "npm", npmrc = "//:.npmrc", pnpm_lock = "//:pnpm-lock.yaml", ) use_repo(npm, "npm")

Module Extensions

npm
Tag Classes
npm_translate_lock

Import a pnpm lock file and create npm_import rules to fetch each package.

These use Bazel's downloader to fetch the packages.
You can use this to redirect all fetches through a store like Artifactory.

See Configuring Bazel's Downloader
for more info about how it works and how to configure it.

The npm_translate_lock module extension tag is the primary user-facing API.
It uses the lockfile format from pnpm because it gives us reliable
semantics for how to dynamically lay out node_modules trees on disk in bazel-out.

To create pnpm-lock.yaml, consider using pnpm import
to preserve the versions pinned by your existing package-lock.json or yarn.lock file.

If you don't have an existing lock file, you can run npx pnpm install --lockfile-only.

Advanced users may want to directly fetch a package from npm rather than start from a lockfile,
npm_import does this.

Generated repository layout

  • A defs.bzl file containing some rules such as npm_link_all_packages, which are documented here.
  • BUILD files declaring targets for the packages listed as dependencies or devDependencies in package.json,
    so you can declare dependencies on those packages without having to repeat version information.

This macro creates a pnpm external repository, if the user didn't create a repository named
"pnpm" prior to calling npm_translate_lock.
rules_js currently only uses this repository when npm_package_lock or yarn_lock are used.
Set pnpm_version to None to inhibit this repository creation.

For more about how to use npm_translate_lock, read pnpm and rules_js.

AttributeTypeDescription
binsdictionary: String → List of strings

Binary files to create in node_modules/.bin for packages in this lock file.

For a given package, this is typically derived from the "bin" attribute in
the package.json file of that package.

For example:

bins = {
    "@foo/bar": {
        "foo": "./foo.js",
        "bar": "./bar.js"
    },
}

Dicts of bins not additive. The most specific match wins.

In the future, this field may be automatically populated from information in the pnpm lock
file. That feature is currently blocked on https://github.com/pnpm/pnpm/issues/5131.

Note: Bzlmod users must use an alternative syntax due to module extensions not supporting
dict-of-dict attributes:

bins = {
    "@foo/bar": [
        "foo=./foo.js",
        "bar=./bar.js"
    ],
}
Default: {}
custom_postinstallsdictionary: String → String

"
A map of package names or package names with their version (e.g., "my-package" or "my-package@v1.2.3")
to a custom postinstall script to apply to the downloaded npm package after its lifecycle scripts runs.
If the version is left out of the package name, the script will run on every version of the npm package. If
a custom postinstall scripts exists for a package as well as for a specific version, the script for the versioned package
will be appended with && to the non-versioned package script.

For example,

custom_postinstalls = {
    "@foo/bar": "echo something > somewhere.txt",
    "fum@0.0.1": "echo something_else > somewhere_else.txt",
},

Custom postinstalls are additive and joined with && when there are multiple matches for a package.
More specific matches are appended to previous matches.

Default: {}
datalist of labels

Data files required by this repository rule when auto-updating the pnpm lock file.

Only needed when update_pnpm_lock is True.
Read more: using update_pnpm_lock

Default: []
external_repository_action_cachestring

The location of the external repository action cache to write to when update_pnpm_lock = True.

Default: ".aspect/rules/external_repository_action_cache"
generate_bzl_library_targetsboolean
Default: False
lifecycle_hooks_envsdictionary: String → List of strings

Environment variables set for the lifecycle hooks actions on npm packages.
The environment variables can be defined per package by package name or globally using "*".
Variables are declared as key/value pairs of the form "key=value".
Multiple matches are additive.

Read more: lifecycles

Default: {}
lifecycle_hooksdictionary: String → List of strings

A dict of package names to list of lifecycle hooks to run for that package.

By default the preinstall, install and postinstall hooks are run if they exist. This attribute allows
the default to be overridden for packages to run prepare.

List of hooks are not additive. The most specific match wins.

Read more: lifecycles

Default: {}
lifecycle_hooks_excludelist of strings

A list of package names or package names with their version (e.g., "my-package" or "my-package@v1.2.3")
to not run any lifecycle hooks on.

Equivalent to adding <value>: [] to lifecycle_hooks.

Read more: lifecycles

Default: []
lifecycle_hooks_execution_requirementsdictionary: String → List of strings

Execution requirements applied to the preinstall, install and postinstall
lifecycle hooks on npm packages.

The execution requirements can be defined per package by package name or globally using "*".

Execution requirements are not additive. The most specific match wins.

Read more: lifecycles

Default: {}
lifecycle_hooks_use_default_shell_envdictionary: String → String

The use_default_shell_env attribute of the lifecycle hooks
actions on npm packages.

See use_default_shell_env

This defaults to False to reduce the negative effects of use_default_shell_env.

Read more: lifecycles

Default: {}
lifecycle_hooks_no_sandboxboolean

If True, a "no-sandbox" execution requirement is added to all lifecycle hooks
unless overridden by lifecycle_hooks_execution_requirements.

Equivalent to adding "*": ["no-sandbox"] to lifecycle_hooks_execution_requirements.

This defaults to True to limit the overhead of sandbox creation and copying the output
TreeArtifacts out of the sandbox.

Read more: lifecycles

Default: True
namename
Default: ""
no_devboolean

If True, devDependencies are not included

Default: False
no_optionalboolean

If True, optionalDependencies are not installed.

Currently npm_translate_lock behaves differently from pnpm in that it downloads all optionalDependencies
while pnpm doesn't download optionalDependencies that are not needed for the platform pnpm is run on.
See https://github.com/pnpm/pnpm/pull/3672 for more context.

Default: False
node_toolchain_prefixstring

the prefix of the node toolchain to use when generating the pnpm lockfile.

Default: "nodejs"
npm_package_locklabel

The package-lock.json file written by npm install.

Only one of npm_package_lock or yarn_lock may be set.

Default: None
npm_package_target_namestring

The name of linked js_library, npm_package or JsInfo producing targets.

When targets are linked as pnpm workspace packages, the name of the target must align with this value.

The {dirname} placeholder is replaced with the directory name of the target.

Default: "pkg"
npmrclabel

The .npmrc file, if any, to use.

When set, the .npmrc file specified is parsed and npm auth tokens and basic authentication configuration
specified in the file are passed to the Bazel downloader for authentication with private npm registries.

In a future release, pnpm settings such as public-hoist-patterns will be used.

Default: None
package_visibilitydictionary: String → List of strings

A map of package names or package names with their version (e.g., "my-package" or "my-package@v1.2.3")
to a visibility list to use for the package's generated node_modules link targets. Multiple matches are additive.
If there are no matches then the package's generated node_modules link targets default to public visibility
(["//visibility:public"]).

Default: {}
patch_toollabel

The patch tool to use. If not specified, the patch from PATH is used.

Default: None
patch_argsdictionary: String → List of strings

A map of package names or package names with their version (e.g., "my-package" or "my-package@v1.2.3")
to a label list arguments to pass to the patch tool. The most specific match wins.

Read more: patching

Default: {"*": ["-p0"]}
patchesdictionary: String → List of strings

A map of package names or package names with their version (e.g., "my-package" or "my-package@v1.2.3")
to a label list of patches to apply to the downloaded npm package. Multiple matches are additive.

These patches are applied after any patches in pnpm.patchedDependencies.

Read more: patching

Default: {}
use_pnpmlabel

label of the pnpm entry point to use.

Default: "@pnpm//:package/bin/pnpm.cjs"
pnpm_locklabel

The pnpm-lock.yaml file, containing resolved and pinned package versions.

Default: None
preupdatelist of labels

Node.js scripts to run in this repository rule before auto-updating the pnpm lock file.

Scripts are run sequentially in the order they are listed. The working directory is set to the root of the
external repository. Make sure all files required by preupdate scripts are added to the data attribute.

A preupdate script could, for example, transform resolutions in the root package.json file from a format
that yarn understands such as @foo/**/bar to the equivalent @foo/*>bar that pnpm understands so that
resolutions are compatible with pnpm when running pnpm import to update the pnpm lock file.

Only needed when update_pnpm_lock is True.
Read more: using update_pnpm_lock

Default: []
public_hoist_packagesdictionary: String → List of strings

A map of package names or package names with their version (e.g., "my-package" or "my-package@v1.2.3")
to a list of Bazel packages in which to hoist the package to the top-level of the node_modules tree when linking.

This is similar to setting https://pnpm.io/npmrc#public-hoist-pattern in an .npmrc file outside of Bazel, however,
wild-cards are not yet supported and npm_translate_lock will fail if there are multiple versions of a package that
are to be hoisted.

public_hoist_packages = {
    "@foo/bar": [""] # link to the root package
    "fum@0.0.1": ["some/sub/package"]
},

List of public hoist packages are additive when there are multiple matches for a package. More specific matches
are appended to previous matches.

Default: {}
quietboolean

Set to False to print info logs and output stdout & stderr of pnpm lock update actions to the console.

Default: True
run_lifecycle_hooksboolean

Sets a default value for lifecycle_hooks if * not already set.
Set this to False to disable lifecycle hooks.

Default: True
update_pnpm_lockboolean

When True, the pnpm lock file will be updated automatically when any of its inputs
have changed since the last update.

Defaults to True when one of npm_package_lock or yarn_lock are set.
Otherwise it defaults to False.

Read more: using update_pnpm_lock

Default: False
use_home_npmrcboolean

Use the $HOME/.npmrc file (or $USERPROFILE/.npmrc when on Windows) if it exists.

Settings from home .npmrc are merged with settings loaded from the .npmrc file specified
in the npmrc attribute, if any. Where there are conflicting settings, the home .npmrc values
will take precedence.

WARNING: The repository rule will not be invalidated by changes to the home .npmrc file since there
is no way to specify this file as an input to the repository rule. If changes are made to the home
.npmrc you can force the repository rule to re-run and pick up the changes by running:
bazel run @{name}//:sync where name is the name of the npm_translate_lock you want to re-run.

Because of the repository rule invalidation issue, using the home .npmrc is not recommended.
.npmrc settings should generally go in the npmrc in your repository so they are shared by all
developers. The home .npmrc should be reserved for authentication settings for private npm repositories.

Default: False
verify_node_modules_ignoredlabel

Bazel 7.x only (deprecated) - Verifies node_modules folders are ignored.

This points to a .bazelignore file to verify that all nested node_modules directories
pnpm will create are listed.

Bazel 8+: Use ignore_directories(["**/node_modules"]) in REPO.bazel instead.

See https://github.com/bazelbuild/bazel/issues/8106

Default: None
verify_patcheslabel

Label to a patch list file.

Use this together with the list_patches macro to guarantee that all patches in a patch folder
are included in the patches attribute.

For example:

verify_patches = "//patches:patches.list",

In your patches folder add a BUILD.bazel file containing.

load("@aspect_rules_js//npm:repositories.bzl", "list_patches")

list_patches(
    name = "patches",
    out = "patches.list",
)

Once you have created this file, you need to create an empty patches.list file before generating the first list. You can do this by running

touch patches/patches.list

Finally, write the patches file at least once to make sure all patches are listed. This can be done by running bazel run //patches:patches_update.

See the list_patches documentation for further info.
NOTE: if you would like to customize the patches directory location, you can set a flag in the .npmrc. Here is an example of what this might look like

# Set the directory for pnpm when patching
# https://github.com/pnpm/pnpm/issues/6508#issuecomment-1537242124
patches-dir=bazel/js/patches

If you do this, you will have to update the verify_patches path to be this path instead of //patches like above.

Default: None
yarn_locklabel

The yarn.lock file written by yarn install.

Only one of npm_package_lock or yarn_lock may be set.

Default: None
npm_import

Import a single npm package into Bazel.

Normally you'd want to use npm_translate_lock to import all your packages at once.
It generates npm_import rules.
You can create these manually if you want to have exact control.

Bazel will only fetch the given package from an external registry if the package is
required for the user-requested targets to be build/tested.

For example, in MODULE.bazel:

npm.npm_import( name = "npm__at_types_node__15.12.2", package = "@types/node", version = "15.12.2", integrity = "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", ) use_repo(npm, "npm__at_types_node__15.12.2") use_repo(npm, "npm__at_types_node__15.12.2__links")

This is similar to Bazel rules in other ecosystems named "_import" like
apple_bundle_import, scala_import, java_import, and py_import.
go_repository is also a model for this rule.

The name of this repository should contain the version number, so that multiple versions of the same
package don't collide.
(Note that the npm ecosystem always supports multiple versions of a library depending on where
it is required, unlike other languages like Go or Python.)

To consume the downloaded package in rules, it must be "linked" into the link package in the
package's BUILD.bazel file:

load("@npm__at_types_node__15.12.2__links//:defs.bzl", npm_link_types_node = "npm_link_imported_package")

npm_link_types_node()

This links @types/node into the node_modules of this package with the target name :node_modules/@types/node.

A :node_modules/@types/node/dir filegroup target is also created that provides the directory artifact of the npm package.
These targets can be used to create entry points for binary target or to access files within the npm package.

NB: You can choose any target name for the link target but we recommend using the node_modules/@scope/name and
node_modules/name convention for readability.

When using npm_translate_lock, you can link all the npm dependencies in the lock file for a package:

load("@npm//:defs.bzl", "npm_link_all_packages")

npm_link_all_packages()

This creates :node_modules/name and :node_modules/@scope/name targets for all direct npm dependencies in the package.
It also creates :node_modules/name/dir and :node_modules/@scope/name/dir filegroup targets that provide the directory artifacts of their npm packages.
These targets can be used to create entry points for binary targets or to access files within the npm package.

If you have a mix of npm_link_all_packages and npm_link_imported_package functions to call you can pass the
npm_link_imported_package link functions to the imported_links attribute of npm_link_all_packages to link
them all in one call. For example,

load("@npm//:defs.bzl", "npm_link_all_packages")
load("@npm__at_types_node__15.12.2__links//:defs.bzl", npm_link_types_node = "npm_link_imported_package")

npm_link_all_packages(
    imported_links = [
        npm_link_types_node,
    ]
)

This has the added benefit of adding the imported_links to the convenience :node_modules target which
includes all direct dependencies in that package.

NB: You can pass an name to npm_link_all_packages and this will change the targets generated to "{name}/@scope/name" and
"{name}/name". We recommend using "node_modules" as the convention for readability.

To change the proxy URL we use to fetch, configure the Bazel downloader:

  1. Make a file containing a rewrite rule like

    rewrite (registry.npmjs.org)/(.*) artifactory.build.internal.net/artifactory/$1/$2

  2. To understand the rewrites, see UrlRewriterConfig in Bazel sources.

  3. Point bazel to the config with a line in .bazelrc like
    common --experimental_downloader_config=.bazel_downloader_config

Read more: Configuring Bazel's Downloader.

AttributeTypeDescription
*packagestring

Name of the npm package, such as acorn or @types/node

root_packagestring

The root package where the node_modules package store is linked to.
Typically this is the package that the pnpm-lock.yaml file is located when using npm_translate_lock.

Default: ""
*versionstring

Version of the npm package, such as 8.4.0

exclude_package_contentslist of strings

List of glob patterns to exclude from the linked package.

This is useful for excluding files that are not needed in the linked package.

For example:

exclude_package_contents = ["**/tests/**"]
Default: []
exclude_package_contents_presetslist of strings
Default: ["basic"]
commitstring

Specific commit to be checked out if url is a git repository.

Default: ""
custom_postinstallstring

Custom string postinstall script to run on the installed npm package.

Runs after any existing lifecycle hooks if any are enabled.

Default: ""
extra_build_contentstring

Additional content to append on the generated BUILD file at the root of
the created repository, either as a string or a list of lines to concatenate.

Default: ""
extract_full_archiveboolean
Default: False
integritystring

Expected checksum of the file downloaded, in Subresource Integrity format.
This must match the checksum of the file downloaded.

This is the same as appears in the pnpm-lock.yaml, yarn.lock or package-lock.json file.

It is a security risk to omit the checksum as remote files can change.

At best omitting this field will make your build non-hermetic.

It is optional to make development easier but should be set before shipping.

Default: ""
lifecycle_hookslist of strings

List of lifecycle hook package.json scripts to run for this package if they exist.

Default: []
npm_authstring

Auth token to authenticate with npm. When using Bearer authentication.

Default: ""
npm_auth_basicstring

Auth token to authenticate with npm. When using Basic authentication.

This is typically the base64 encoded string "username:password".

Default: ""
npm_auth_passwordstring

Auth password to authenticate with npm. When using Basic authentication.

Default: ""
npm_auth_usernamestring

Auth username to authenticate with npm. When using Basic authentication.

Default: ""
patch_toollabel

The patch tool to use. If not specified, the patch from PATH is used.

Default: None
patch_argslist of strings

Arguments to pass to the patch tool.

-p1 will usually be needed for patches generated by git.

Default: ["-p0"]
patcheslist of labels

Patch files to apply onto the downloaded npm package.

Default: []
urlstring

Optional url for this package. If unset, a default npm registry url is generated from
the package name and version.

May start with git+ssh:// or git+https:// to indicate a git repository. For example,

git+ssh://git@github.com/org/repo.git

If url is configured as a git repository, the commit attribute must be set to the
desired commit.

Default: ""
binsdictionary: String → String

Dictionary of node_modules/.bin binary files to create mapped to their node entry points.

This is typically derived from the "bin" attribute in the package.json
file of the npm package being linked.

For example:

bins = {
    "foo": "./foo.js",
    "bar": "./bar.js",
}

In the future, this field may be automatically populated by npm_translate_lock
from information in the pnpm lock file. That feature is currently blocked on
https://github.com/pnpm/pnpm/issues/5131.

Default: {}
depsdictionary: String → String

A dict other npm packages this one depends on where the key is the package name and value is the version

Default: {}
lifecycle_build_targetboolean
Default: False
lifecycle_hooks_envlist of strings

Environment variables set for the lifecycle hooks action for this npm
package if there is one.

Environment variables are defined by providing an array of "key=value" entries.

For example:

lifecycle_hooks_env: ["PREBULT_BINARY=https://downloadurl"],
Default: []
lifecycle_hooks_execution_requirementslist of strings

Execution requirements when running the lifecycle hooks.

For example:

lifecycle_hooks_execution_requirements: ["no-sandbox", "requires-network"]

This defaults to ["no-sandbox"] to limit the overhead of sandbox creation and copying the output
TreeArtifact out of the sandbox.

Default: ["no-sandbox"]
lifecycle_hooks_use_default_shell_envboolean

If True, the use_default_shell_env attribute of lifecycle hook actions is set to True.

See use_default_shell_env

This defaults to False to reduce the negative effects of use_default_shell_env.

Default: False
package_visibilitylist of strings

Visibility of generated node_module link targets.

Default: ["//visibility:public"]
replace_packagestring

Use the specified npm_package target when linking instead of the fetched sources for this npm package.

The injected npm_package target may optionally contribute transitive npm package dependencies on top
of the transitive dependencies specified in the pnpm lock file for the same package, however, these
transitive dependencies must not collide with pnpm lock specified transitive dependencies.

Any patches specified for this package will be not applied to the injected npm_package target. They
will be applied, however, to the fetches sources so they can still be useful for patching the fetched
package.json file, which is used to determine the generated bin entries for the package.

NB: lifecycle hooks and custom_postinstall scripts, if implicitly or explicitly enabled, will be run on
the injected npm_package. These may be disabled explicitly using the lifecycle_hooks attribute.

Default: ""
namename
Default: ""
npm_exclude_package_contents

Configuration for excluding package contents from npm packages.

This tag can be used multiple times to specify different exclusion patterns for different package specifiers.
More specific package matches override less specific ones (the wildcard "*" is only used if no specific
package match is found).

By default, presets is set to ["basic"] which excludes common files such as *.md and development-related
files. Multiple presets can be combined.

Example:

npm.npm_exclude_package_contents(
    package = "*",
    patterns = ["**/docs/**"],
)
npm.npm_exclude_package_contents(
    package = "my-package@1.2.3",
    # Overrides the "*" config for this specific package
    presets = ["yarn_autoclean"],
)
AttributeTypeDescription
*packagestring

Package name to apply exclusions to. Supports wildcards like '*' for all packages.

patternslist of strings

List of glob patterns to exclude from the specified package.

Default: []
presetslist of strings

Which preset exclusion patterns to include. Multiple presets can be combined. Valid values:

Default: ["basic"]
npm_replace_package

Replace a package with a custom target.

This allows replacing packages declared in package.json with custom implementations.
Multiple npm_replace_package tags can be used to replace different packages.

Targets must produce JsInfo or NpmPackageInfo providers such as js_library or npm_package targets.

The injected package targets may optionally contribute transitive npm package dependencies on top
of the transitive dependencies specified in the pnpm lock file for their respective packages, however, these
transitive dependencies must not collide with pnpm lock specified transitive dependencies.

Any patches specified for the packages will be not applied to the injected package targets. They
will be applied, however, to the fetched sources for their respective packages so they can still be useful
for patching the fetched package.json files, which are used to determine the generated bin entries for packages.

NB: lifecycle hooks and custom_postinstall scripts, if implicitly or explicitly enabled, will be run on
the injected package targets. These may be disabled explicitly using the lifecycle_hooks attribute.

Example:

npm.npm_replace_package( package = "chalk@5.3.0", replacement = "@chalk_501//:pkg", )
AttributeTypeDescription
*packagestring

The package name and version to replace (e.g., 'chalk@5.3.0')

*replacementlabel

The target to use as replacement for this package

pnpm
Tag Classes
pnpm
AttributeTypeDescription
namename

Name of the generated repository, allowing more than one pnpm version to be registered.
Overriding the default is only permitted in the root module.

Default: "pnpm"
include_npmboolean

If true, include the npm package along with the pnpm binary.

Default: False
pnpm_versionstring

pnpm version to use. The string latest will be resolved to LATEST_PNPM_VERSION.

Default: "10.30.2"
pnpm_version_fromlabel

Label to a package.json file to read the pnpm version from.

It should appear as an attribute like "packageManager": "pnpm@10.20.0"

Default: None
pnpm_version_integritystring
Default: ""