6.8 KiB
Bun rules for Bazel
rules_bun provides Bazel rules for running, testing, building, compiling,
bundling, and developing JavaScript and TypeScript code with Bun.
Repository layout
This repository follows the standard Bazel ruleset layout:
/
MODULE.bazel
README.md
bun/
BUILD.bazel
defs.bzl
extensions.bzl
repositories.bzl
toolchain.bzl
docs/
examples/
tests/
The public entrypoint for rule authors and users is @rules_bun//bun:defs.bzl.
Public API
rules_bun exports these primary rules:
bun_binarybun_buildbun_compilebun_bundlebun_devbun_scriptbun_testjs_binaryjs_testjs_run_devserverjs_libraryts_library
Reference documentation:
- Published docs site: https://eriyc.github.io/rules_bun/
- Generated build rule reference: docs/rules.md
bun_installextension docs: docs/bun_install.md- Docs index: docs/index.md
To refresh generated rule docs:
bazel build //docs:rules_md && cp bazel-bin/docs/rules.md docs/rules.md
Bzlmod usage
Release announcements should provide a copy-pasteable module snippet in the standard ruleset form:
bazel_dep(name = "rules_bun", version = "0.5.0")
Then add the Bun repositories and register the toolchains in MODULE.bazel:
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_linux_x64",
"bun_linux_aarch64",
"bun_linux_x64_musl",
"bun_linux_aarch64_musl",
"bun_darwin_x64",
"bun_darwin_aarch64",
"bun_windows_x64",
"bun_windows_aarch64",
)
register_toolchains(
"@rules_bun//bun:darwin_aarch64_toolchain",
"@rules_bun//bun:darwin_x64_toolchain",
"@rules_bun//bun:linux_aarch64_toolchain",
"@rules_bun//bun:linux_x64_toolchain",
"@rules_bun//bun:windows_x64_toolchain",
)
If you want Bazel-managed dependency installation, also add the module
extension for bun_install:
bun_install runs bun install, not npm install. In the example below,
bun_deps is just the Bazel repository name for the generated
node_modules tree. See docs/bun_install.md for the
full extension reference.
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install(
name = "bun_deps",
package_json = "//:package.json",
bun_lockfile = "//:bun.lock",
# Optional: include extra install-time files or allow Bun to reuse the
# host HOME/cache.
# install_inputs = ["//:.npmrc"],
# isolated_home = False,
)
use_repo(bun_install_ext, "bun_deps")
rules_js compatibility layer
rules_bun now exposes a Bun-backed compatibility layer for the most common
rules_js entrypoints:
@rules_bun//js:defs.bzlexportsjs_binary,js_test,js_run_devserver,js_library,ts_library, andJsInfo.@rules_bun//npm:extensions.bzlexportsnpm_translate_lock, which creates a Bun-installed external repo and generates@<repo>//:defs.bzlwithnpm_link_all_packages().
Example:
load("@rules_bun//js:defs.bzl", "js_binary")
load("@npm//:defs.bzl", "npm_link_all_packages")
npm_link_all_packages()
js_binary(
name = "app",
entry_point = "src/main.ts",
node_modules = ":node_modules",
)
This is a compatibility subset, not a full reimplementation of rules_js.
Package aliases created by npm_link_all_packages() use sanitized target names
such as npm__vite or npm__at_types_node.
Legacy WORKSPACE usage
For non-Bzlmod consumers, the repository exposes a legacy setup macro in
@rules_bun//bun:repositories.bzl:
load("@rules_bun//bun:repositories.bzl", "bun_register_toolchains")
bun_register_toolchains()
Loading rules in BUILD files
load(
"@rules_bun//bun:defs.bzl",
"bun_binary",
"bun_build",
"bun_compile",
"bun_bundle",
"bun_dev",
"bun_script",
"bun_test",
"js_library",
"ts_library",
)
Common workflows
bun_script for package scripts
Use bun_script to expose a package.json script as a Bazel executable.
This is the recommended way to run Vite-style dev, build, and preview
scripts.
load("@rules_bun//bun:defs.bzl", "bun_script")
bun_script(
name = "web_dev",
script = "dev",
package_json = "package.json",
node_modules = "@bun_deps//:node_modules",
data = glob([
"src/**",
"static/**",
"vite.config.*",
"svelte.config.*",
"tsconfig*.json",
]),
)
When node_modules is provided, executables from node_modules/.bin are added
to PATH. This label typically comes from bun_install, which still produces a
standard node_modules/ directory.
bun_build and bun_compile
Use bun_build for general-purpose bun build output directories and
bun_compile for standalone executables built with bun build --compile.
load("@rules_bun//bun:defs.bzl", "bun_build", "bun_compile")
bun_build(
name = "site",
entry_points = ["src/index.html"],
data = glob(["src/**"]),
splitting = True,
metafile = True,
)
bun_compile(
name = "cli",
entry_point = "src/cli.ts",
)
bun_build exposes a directory output so Bun can emit HTML, CSS, assets, and
split chunks. bun_compile produces a single executable artifact and supports
explicit cross-compilation via compile_executable. When root is omitted,
bun_build derives a stable default from the entry point parent directory so
HTML and asset output stays inside Bazel's declared output tree.
bun_dev for local development
Use bun_dev for long-running watch or hot-reload development targets.
load("@rules_bun//bun:defs.bzl", "bun_dev")
bun_dev(
name = "web_dev",
entry_point = "src/main.ts",
# Optional: run from the entry point directory so Bun auto-loads colocated .env files.
# working_dir = "entry_point",
)
Supported development options include:
watch_mode = "watch"watch_mode = "hot"restart_on = [...]working_dir = "workspace" | "entry_point"
Working directory behavior
bun_binary and bun_dev support working_dir:
"workspace": run from the Bazel runfiles workspace root."entry_point": run from the nearest ancestor of the entry point that contains.envorpackage.json.
Tests and examples
The repository keeps conformance and integration coverage in tests/ and usage samples in examples/.
Representative example docs:
To validate the ruleset locally:
bazel test //tests/...