@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",
)
Macros
There are two sets of macros for building Next.js applications: standard and standalone.
Standard
nextjs(): wrap the build+dev+start targetsnextjs_build(): the Next.js build commandnextjs_dev(): the Next.js dev commandnextjs_start(): the Next.js start command,
accepting a Next.js build artifact to start
Standalone
nextjs_standalone_build(): the Next.js build command,
configured for a standalone application within bazelnextjs_standalone_server(): constructs a standalone Next.js serverjs_binaryfollowing the
standalone directory structure guidelines
Functions & Macros
nextjsGenerates 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. |
*next_js_binary | The next Typically this is a js_binary target created using See main docstring above for example usage. |
config | the Next.js config file. Typically Default: "next.config.mjs" |
data | Data files to include in all targets. Default: [] |
serve_data | Data files to include in devserver targets Default: [] |
kwargs | Other attributes passed to all targets such as |
nextjs_buildBuild 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 Typically this is a js_binary target created using 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 |
nextjs_startRun 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 |
*next_js_binary | The next Typically this is a js_binary target created using See main docstring above for example usage. |
data | additional server data Default: [] |
kwargs | Other attributes passed to all targets such as |
nextjs_devRun the Next.js development server.
See https://nextjs.org/docs/pages/api-reference/cli/next#next-dev-options
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 Typically this is a js_binary target created using See main docstring above for example usage. |
kwargs | Other attributes passed to all targets such as |
nextjs_standalone_buildCompile a standalone Next.js application.
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 |
nextjs_standalone_serverConfigures 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 |
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 Default: [] |
kwargs | additional |
@aspect_rules_js//js/private:js_binary.bzl
Rules for running JavaScript programs under Bazel, as tools or with bazel run or bazel test.
For example, this binary references the acorn npm package which was already linked
using an API like npm_link_all_packages.
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_test") js_binary( name = "bin", # Reference the location where the acorn npm module was linked in the root Bazel package data = ["//:node_modules/acorn"], entry_point = "require_acorn.js", )
Functions & Macros
js_binary_lib.create_launcherParameters
*ctx | |
*log_prefix_rule_set | |
*log_prefix_rule | |
fixed_args | Default: [] |
fixed_env | Default: {} |
js_binary_lib.implementationParameters
*ctx |
Rules
js_binaryExecute a program in the Node.js runtime.
The version of Node.js is determined by Bazel's toolchain selection. In the WORKSPACE you used
nodejs_register_toolchains to provide options to Bazel. Then Bazel selects from these options
based on the requested target platform. Use the
--toolchain_resolution_debug
Bazel option to see more detail about the selection.
All common binary attributes are supported
including args as the list of arguments passed Node.js.
Node.js execution is performed by a shell script that sets environment variables and runs the Node.js binary with the entry_point script.
The shell script is located relative to the directory containing the js_binary at \{name\}_/\{name\} similar to other rulesets
such as rules_go. See PR #1690 for more information on this naming scheme.
The following environment variables are made available to the Node.js runtime based on available Bazel Make variables:
- JS_BINARY__BINDIR: the WORKSPACE-relative Bazel bin directory; equivalent to the
$(BINDIR)Make variable of thejs_binarytarget - JS_BINARY__COMPILATION_MODE: One of
fastbuild,dbg, oroptas set by--compilation_mode; equivalent to$(COMPILATION_MODE)Make variable of thejs_binarytarget - JS_BINARY__TARGET_CPU: the target cpu architecture; equivalent to
$(TARGET_CPU)Make variable of thejs_binarytarget
The following environment variables are made available to the Node.js runtime based on the rule context:
- JS_BINARY__BUILD_FILE_PATH: the WORKSPACE-relative path to the BUILD file of the Bazel target being run; equivalent to
ctx.build_file_pathof thejs_binarytarget's rule context - JS_BINARY__PACKAGE: the package of the Bazel target being run; equivalent to
ctx.label.packageof thejs_binarytarget's rule context - JS_BINARY__TARGET: the full label of the Bazel target being run; a stringified version of
ctx.labelof thejs_binarytarget's rule context - JS_BINARY__TARGET_NAME: the name of the Bazel target being run; equivalent to
ctx.label.nameof thejs_binarytarget's rule context - JS_BINARY__WORKSPACE: the Bazel workspace name; equivalent to
ctx.workspace_nameof thejs_binarytarget's rule context
The following environment variables are made available to the Node.js runtime based the runtime environment:
- JS_BINARY__NODE_BINARY: the Node.js binary path run by the
js_binarytarget - JS_BINARY__NPM_BINARY: the npm binary path; this is available when
include_npmisTrueon thejs_binarytarget - JS_BINARY__NODE_WRAPPER: the Node.js wrapper script used to run Node.js which is available as
nodeon thePATHat runtime - JS_BINARY__RUNFILES: the absolute path to the Bazel runfiles directory
- JS_BINARY__EXECROOT: the absolute path to the root of the execution root for the action; if in the sandbox, this path absolute path to the root of the execution root within the sandbox
| Attribute | Type | Description |
|---|---|---|
*name | name | A unique name for this target. |
chdir | string | Working directory to run the binary or test in, relative to the workspace. By default, To run in the directory containing the
(or if you're in a macro, use WARNING: this will affect other paths passed to the program, either as arguments or in configuration files, You may need
Default: "" |
data | list of labels | Runtime dependencies of the program. The transitive closure of the NB: Default: [] |
*entry_point | label | The main script which is evaluated by node.js. This is the module referenced by the This must be a target that provides a single file or a See https://github.com/bazel-contrib/bazel-lib/blob/main/docs/directory_path.md |
*enable_runfiles | boolean | Whether runfiles are enabled in the current build configuration. Typical usage of this rule is via a macro which automatically sets this |
env | dictionary: String → String | Environment variables of the action. Subject to $(location) Default: {} |
expand_args | boolean | Enables $(location) This comes at some analysis-time cost even for a set of args that does not have any expansions. Default: True |
expand_env | boolean | Enables $(location) This comes at some analysis-time cost even for a set of envs that does not have any expansions. Default: True |
fixed_args | list of strings | Fixed command line arguments to pass to the Node.js when this Subject to $(location) Unlike the built-in
See https://bazel.build/reference/be/common-definitions#common-attributes-binaries Default: [] |
node_options | list of strings | Options to pass to the node invocation on the command line. https://nodejs.org/api/cli.html These options are passed directly to the node invocation on the command line. Default: [] |
expected_exit_code | integer | The expected exit code. Can be used to write tests that are expected to fail. Default: 0 |
log_level | string | Set the logging level. Log from are written to stderr. They will be supressed on success when running as the tool Log levels: fatal, error, warn, info, debug Default: "error" |
patch_node_fs | boolean | Patch the to Node.js When enabled, When disabled, node programs can leave the execroot, runfiles and sandbox by following symlinks Default: True |
include_sources | boolean | When True, Default: True |
include_transitive_sources | boolean | When True, Default: True |
include_types | boolean | When True, Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip NB: These are types from direct Default: False |
include_transitive_types | boolean | When True, Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip Default: False |
include_npm_sources | boolean | When True, files in
Default: True |
preserve_symlinks_main | boolean | When True, the --preserve-symlinks-main flag is passed to node. This prevents node from following an ESM entry script out of runfiles and the sandbox. This can happen for This flag was added in Node.js v10.2.0 (released 2018-05-23). If your node toolchain is configured to use a See https://nodejs.org/api/cli.html#--preserve-symlinks-main for more information. Default: True |
no_copy_to_bin | list of labels | List of files to not copy to the Bazel output tree when This is useful for exceptional cases where a Default: [] |
copy_data_to_bin | boolean | When True, Defaults to True so that a Setting this to False is more optimal in terms of inputs, but there is a yet unresolved issue of ESM imports Default: True |
include_npm | boolean | When True, npm is included in the runfiles of the target. An npm binary is also added on the PATH so tools can spawn npm processes. This is a bash script A minimum of rules_nodejs version 5.7.0 is required which contains the Node.js toolchain changes Default: False |
node_toolchain | label | The Node.js runtime toolchain to use for this target. See https://bazel-contrib.github.io/rules_nodejs/Toolchains.html Typically this is left unset so that Bazel automatically selects the right Node.js toolchain Default: None |
js_testIdentical to js_binary, but usable under bazel test.
All common test attributes are
supported including args as the list of arguments passed Node.js.
Bazel will set environment variables when a test target is run under bazel test and bazel run
that a test runner can use.
A runner can write arbitrary outputs files it wants Bazel to pickup and save with the test logs to
TEST_UNDECLARED_OUTPUTS_DIR. These get zipped up and saved along with the test logs.
JUnit XML reports can be written to XML_OUTPUT_FILE for Bazel to consume.
TEST_TMPDIR is an absolute path to a private writeable directory that the test runner can use for
creating temporary files.
LCOV coverage reports can be written to COVERAGE_OUTPUT_FILE when running under bazel coverage
or if the --coverage flag is set.
See the Bazel Test encyclopedia for details on
the contract between Bazel and a test runner.
| Attribute | Type | Description |
|---|---|---|
*name | name | A unique name for this target. |
chdir | string | Working directory to run the binary or test in, relative to the workspace. By default, To run in the directory containing the
(or if you're in a macro, use WARNING: this will affect other paths passed to the program, either as arguments or in configuration files, You may need
Default: "" |
data | list of labels | Runtime dependencies of the program. The transitive closure of the NB: Default: [] |
*entry_point | label | The main script which is evaluated by node.js. This is the module referenced by the This must be a target that provides a single file or a See https://github.com/bazel-contrib/bazel-lib/blob/main/docs/directory_path.md |
*enable_runfiles | boolean | Whether runfiles are enabled in the current build configuration. Typical usage of this rule is via a macro which automatically sets this |
env | dictionary: String → String | Environment variables of the action. Subject to $(location) Default: {} |
expand_args | boolean | Enables $(location) This comes at some analysis-time cost even for a set of args that does not have any expansions. Default: True |
expand_env | boolean | Enables $(location) This comes at some analysis-time cost even for a set of envs that does not have any expansions. Default: True |
fixed_args | list of strings | Fixed command line arguments to pass to the Node.js when this Subject to $(location) Unlike the built-in
See https://bazel.build/reference/be/common-definitions#common-attributes-binaries Default: [] |
node_options | list of strings | Options to pass to the node invocation on the command line. https://nodejs.org/api/cli.html These options are passed directly to the node invocation on the command line. Default: [] |
expected_exit_code | integer | The expected exit code. Can be used to write tests that are expected to fail. Default: 0 |
log_level | string | Set the logging level. Log from are written to stderr. They will be supressed on success when running as the tool Log levels: fatal, error, warn, info, debug Default: "error" |
patch_node_fs | boolean | Patch the to Node.js When enabled, When disabled, node programs can leave the execroot, runfiles and sandbox by following symlinks Default: True |
include_sources | boolean | When True, Default: True |
include_transitive_sources | boolean | When True, Default: True |
include_types | boolean | When True, Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip NB: These are types from direct Default: False |
include_transitive_types | boolean | When True, Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip Default: False |
include_npm_sources | boolean | When True, files in
Default: True |
preserve_symlinks_main | boolean | When True, the --preserve-symlinks-main flag is passed to node. This prevents node from following an ESM entry script out of runfiles and the sandbox. This can happen for This flag was added in Node.js v10.2.0 (released 2018-05-23). If your node toolchain is configured to use a See https://nodejs.org/api/cli.html#--preserve-symlinks-main for more information. Default: True |
no_copy_to_bin | list of labels | List of files to not copy to the Bazel output tree when This is useful for exceptional cases where a Default: [] |
copy_data_to_bin | boolean | When True, Defaults to True so that a Setting this to False is more optimal in terms of inputs, but there is a yet unresolved issue of ESM imports Default: True |
include_npm | boolean | When True, npm is included in the runfiles of the target. An npm binary is also added on the PATH so tools can spawn npm processes. This is a bash script A minimum of rules_nodejs version 5.7.0 is required which contains the Node.js toolchain changes Default: False |
node_toolchain | label | The Node.js runtime toolchain to use for this target. See https://bazel-contrib.github.io/rules_nodejs/Toolchains.html Typically this is left unset so that Bazel automatically selects the right Node.js toolchain Default: None |
env_inherit | list of strings | Specifies additional environment variables to inherit from the external environment when the test is executed by bazel test. Default: [] |
@aspect_rules_js//js/private:js_image_layer.bzl
Rules for creating container image layers from js_binary targets
For example, this js_image_layer target outputs node_modules.tar and app.tar with /app prefix.
load("@aspect_rules_js//js:defs.bzl", "js_image_layer") js_image_layer( name = "layers", binary = "//label/to:js_binary", root = "/app", )
Functions & Macros
js_image_layer_lib.implementationParameters
*ctx |
Rules
js_image_layerCreate 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.
nodelayer contains the Node.js toolchainpackage_store_3player contains all 3p npm deps in thenode_modules/.aspect_rules_jspackage storepackage_store_1player contains all 1p npm deps in thenode_modules/.aspect_rules_jspackage storenode_moduleslayer contains allnode_modules/*symlinks which point into the package storeapplayer 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_jspackage store follows the same pattern as the pnpm
node_modules/.pnpmvirtual 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" ] )
Performance
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:
layer_groupsare checked in order first- If no match is found for
layer_groups, thedefault layer groupsare checked. - 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.
}
| Attribute | Type | Description |
|---|---|---|
*name | name | A unique name for this target. |
*binary | label | Label to an js_binary target |
root | string | Path where the files from js_binary will reside in. eg: /apps/app1 or /app Default: "" |
owner | string | Owner of the entries, in Default: "0:0" |
directory_mode | string | Mode of the directories, in Default: "0755" |
file_mode | string | Mode of the files, in Default: "0555" |
compression | string | Compression algorithm. See https://github.com/bazel-contrib/bazel-lib/blob/bdc6ade0ba1ebe88d822bcdf4d4aaa2ce7e2cd37/lib/private/tar.bzl#L29-L39 Default: "gzip" |
platform | label | Platform to transition. Default: None |
preserve_symlinks | string | Preserve symlinks for entries matching the pattern. Default: ".*/node_modules/.*" |
layer_groups | dictionary: String → String | Layer groups to create. Default: {} |
@aspect_rules_js//js/private:js_info_files.bzl
Helper rule to gather files from JsInfo providers of targets and provide them as default outputs
Rules
js_info_filesGathers 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.
| Attribute | Type | Description |
|---|---|---|
*name | name | A unique name for this target. |
srcs | list of labels | List of targets to gather files from. Default: [] |
include_sources | boolean | When True, Default: True |
include_transitive_sources | boolean | When True, Default: True |
include_types | boolean | When True, Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip NB: These are types from direct Default: False |
include_transitive_types | boolean | When True, Defaults to False since types are generally not needed at runtime and introducing them could slow down developer round trip Default: False |
include_npm_sources | boolean | When True, files in
Default: True |
@aspect_rules_js//js/private:js_library.bzl
js_library groups together JS sources and arranges them and their transitive and npm dependencies into a provided
JsInfo. There are no Bazel actions to run.
For example, this BUILD file groups a pair of .js/.d.ts files along with the package.json.
The latter is needed because it contains a typings key that allows downstream
users of this library to resolve the one.d.ts file.
The main key is another commonly used field in package.json which would require including it in the library.
load("@aspect_rules_js//js:defs.bzl", "js_library") js_library( name = "one", srcs = [ "one.d.ts", "one.js", "package.json", ], )
| This is similar to py_library which depends on
| Python sources and provides a PyInfo.
Functions & Macros
js_library_lib.implementationParameters
*ctx |
Rules
js_libraryA 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.
| Attribute | Type | Description |
|---|---|---|
*name | name | A unique name for this target. |
srcs | list 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 Source files that are JSON files, declaration files or directory artifacts will be automatically provided as Default: [] |
types | list of labels | Same as For example, a js_library with only Default: [] |
deps | list 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 If this list contains linked npm packages, npm package store targets or other targets that provide NB: Linked npm package targets that are "dev" dependencies do not forward their underlying Default: [] |
data | list 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 If this list contains linked npm packages, npm package store targets or other targets that provide NB: Linked npm package targets that are "dev" dependencies do not forward their underlying Default: [] |
no_copy_to_bin | list of labels | List of files to not copy to the Bazel output tree when This is useful for exceptional cases where a Default: [] |
copy_data_to_bin | boolean | When True, Default: True |
@aspect_rules_js//js/private:js_run_binary.bzl
Runs a js_binary as a build action.
This macro wraps Aspect bazel-lib's run_binary (https://github.com/bazel-contrib/bazel-lib/blob/main/lib/run_binary.bzl)
and adds attributes and features specific to rules_js's js_binary.
Load this with,
load("@aspect_rules_js//js:defs.bzl", "js_run_binary")
Functions & Macros
js_run_binaryWrapper 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 WORKSPACE-relative bazel bin directory; equivalent to the
$(BINDIR)Make variable of thejs_run_binarytarget - BAZEL_COMPILATION_MODE: One of
fastbuild,dbg, oroptas set by--compilation_mode; equivalent to$(COMPILATION_MODE)Make variable of thejs_run_binarytarget - BAZEL_TARGET_CPU: the target cpu architecture; equivalent to
$(TARGET_CPU)Make variable of thejs_run_binarytarget
The following environment variables are made available to the Node.js runtime based on the rule context:
- BAZEL_BUILD_FILE_PATH: the WORKSPACE-relative path to the BUILD file of the bazel target being run; equivalent to
ctx.build_file_pathof thejs_run_binarytarget's rule context - BAZEL_PACKAGE: the package of the bazel target being run; equivalent to
ctx.label.packageof thejs_run_binarytarget's rule context - BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of
ctx.labelof thejs_run_binarytarget's rule context - BAZEL_TARGET: the name of the bazel target being run; equivalent to
ctx.label.nameof thejs_run_binarytarget's rule context - BAZEL_WORKSPACE: the bazel workspace name; equivalent to
ctx.workspace_nameof thejs_run_binarytarget's rule context
Parameters
*name | Target name |
*tool | The tool to run in the action. Should be a |
env | Environment variables of the action. Subject to Default: {} |
srcs | Additional inputs of the action. These labels are available for Default: [] |
outs | Output files generated by the action. These labels are available for Default: [] |
out_dirs | Output directories generated by the action. These labels are not available for Default: [] |
args | Command line arguments of the binary. Subject to Default: [] |
chdir | Working directory to run the build action in. This overrides the chdir value if set on the By default, To run in the directory containing the js_run_binary in the output tree, use WARNING: this will affect other paths passed to the program, either as arguments or in configuration files, You may need 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 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 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 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 Runfiles of Using the entry point script that is in the execroot output tree means that there will be no conflicting When True, the 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 Default: True |
include_types | see Default: False |
include_transitive_sources | see Default: True |
include_transitive_types | see Default: False |
include_npm_sources | see Default: True |
log_level | Set the logging level of the This overrides the log level set on the 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, Default: None |
execution_requirements | Information for scheduling the action. For example,
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:
Default value is When stamping is enabled, an additional two environment variables will be set for the action: 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 When enabled, When disabled, node programs can leave the execroot, runfiles and sandbox by following symlinks Default: True |
allow_execroot_entry_point_with_no_copy_data_to_bin | Turn off validation that the See Default: False |
use_default_shell_env | If set, passed to the underlying run_binary. May introduce non-determinism when True; use with care! Requires a minimum of bazel_lib v1.40.3 or v2.4.2. Refer to https://bazel.build/rules/lib/builtins/actions#run for more details. Default: None |
kwargs | Additional arguments |
@aspect_rules_js//js/private:js_run_devserver.bzl
Implementation details for js_run_devserver rule
Functions & Macros
js_run_devserverRuns 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 Default: None |
command | The devserver command to run. For example, this could be the bin entry of an npm package that is included Using the bin entry of next, for example, resolves issues with Next.js and React Only one of 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 See https://github.com/aspect-build/rules_js/issues/935 for more context. Default: False |
use_execroot_entry_point | Use the Using the entry point script that is in the execroot output tree means that there will be no conflicting When True, the Default: True |
allow_execroot_entry_point_with_no_copy_data_to_bin | Turn off validation that the See Default: False |
kwargs | All other args from
See https://docs.aspect.build/rules/aspect_rules_js/docs/js_binary |
@aspect_rules_js//npm/private:npm_import.bzl
This uses Bazel's downloader to fetch the packages.
You can use this to redirect all fetches through a store like Artifactory.
See https://blog.aspect.build/configuring-bazels-downloader for more info about how it works
and how to configure it.
See npm_translate_lock for the primary user-facing API to fetch npm packages
for a given lockfile.
Functions & Macros
npm_importParameters
*name | |
*key | |
*package | |
*version | |
*deps | |
*deps_constraints | |
*extra_build_content | |
*transitive_closure | |
*root_package | |
*lifecycle_hooks | |
*lifecycle_hooks_execution_requirements | |
*lifecycle_hooks_env | |
*lifecycle_hooks_use_default_shell_env | |
*integrity | |
*url | |
*commit | |
*replace_package | |
*package_visibility | |
*patch_tool | |
*patch_args | |
*patches | |
*custom_postinstall | |
*npm_auth | |
*npm_auth_basic | |
*npm_auth_username | |
*npm_auth_password | |
*bins | |
*dev | |
*generate_bzl_library_targets | |
*generate_package_json_bzl | |
*extract_full_archive | |
*exclude_package_contents |
@aspect_rules_js//npm/private:npm_link_package.bzl
npm_link_package rule
Functions & Macros
npm_link_package"Create a package store entry with the provided source and link to node_modules.
This is a convenience macro that creates both an npm_package_store and a a single npm_link_package_store
to link the package into node_modules/<package>.
A {name}/dir filegroup is also generated that refers to a directory artifact can be used to access
the package directory for creating entry points or accessing files in the package.
Parameters
*name | The name of the link target to create if |
*src | the target to link; may only to be specified when linking in the root package |
deps | list of npm_package_store; may only to be specified when linking in the root package Default: {} |
auto_manual | whether or not to automatically add a manual tag to the generated targets Default: True |
visibility | the visibility of the link target Default: ["//visibility:public"] |
kwargs | see attributes of npm_package_store rule |
@aspect_rules_js//npm/private:npm_package.bzl
Rules for linking npm dependencies and packaging and linking first-party deps.
Load these with,
load("@aspect_rules_js//npm:defs.bzl", "npm_package")
Functions & Macros
npm_package_lib.implementationParameters
*ctx |
npm_packageA 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:
-
include_external_repositories -
include_srcs_packages -
exclude_srcs_packages -
root_paths -
include_srcs_patterns -
exclude_srcs_patterns -
replace_prefixes
For more information 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_sourfes 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 Default: [] |
data | Runtime / linktime npm dependencies of this npm package.
Gathered Default: [] |
args | Arguments that are passed down to Default: [] |
out | Path of the output directory, relative to this package. Default: None |
package | The package name. If set, should match the If set, the package name set here will be used for linking if a npm_link_package does not specify a package name. A If unset, a npm_link_package that references this npm_package must define the package name must be for linking. Default: "" |
version | The package version. If set, should match the If set, a npm_link_package may omit the package version and the package version set here will be used for linking. A If unset, a npm_link_package that references this npm_package must define the package version must be 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 Matching is done on the parent directory of the output file path so a trailing '**' glob patterm Forward slashes ( A Defaults to 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 When copied from an external repository, the file path in the output directory For example, the following copies
Files that come from matching external are subject to subsequent filters and 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 Forward slashes ( Defaults to ["./**"] which includes sources target's package and subpackages. Files that have matching Bazel packages are subject to subsequent filters and 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 Forward slashes ( Defaults to ["/node_modules/"] which excludes all node_modules folders Files that have do not have matching Bazel packages are subject to subsequent 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 Forward slashes ( Defaults to Files that have matching output directory paths are subject to subsequent 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 Forward slashes ( Files that do not have matching output directory paths are subject to subsequent 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 Forward slashes ( Replace prefix transformation are the final step in the list of filters and transformations. 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. Default: False |
include_sources | When True, Default: True |
include_types | When True, Default: True |
include_transitive_sources | When True, Default: True |
include_transitive_types | When True, Default: True |
include_npm_sources | When True, Default: False |
include_runfiles | When True, default runfiles from This may be needed in a few cases:
NB: The default value will be flipped to False in the next major release as runfiles are not needed in the general case 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 Since Bazel removes write permissions on files in the output tree after an action completes,
Default: "auto" |
publishable | When True, enable generation of Default: False |
verbose | If true, prints out verbose logs to stdout Default: False |
kwargs | Additional attributes such as |
stamped_package_jsonConvenience 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 |
*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/private:npm_translate_lock.bzl
Logic to fetch npm packages for a lockfile.
These use Bazel's downloader to fetch the packages.
You can use this to redirect all fetches through a store like Artifactory.
See https://blog.aspect.build/configuring-bazels-downloader for more info about how it works
and how to configure it.
The npm_translate_lock bazel 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.
Functions & Macros
list_patchesWrite a file containing a list of all patches in the current folder to the source tree.
Use this together with the verify_patches attribute of npm_translate_lock to verify
that all patches in a patch folder are included. This macro stamps a test to ensure the
file stays up to date.
Parameters
*name | Name of the target |
out | Name of file to write to the source tree. If unspecified, Default: None |
include_patterns | Patterns to pass to a glob of patch files Default: ["*.diff", "*.patch"] |
exclude_package_contents | Patterns to ignore in a glob of patch files Default: [] |