4.7 KiB
rules_bun
Bazel rules for bun.
Rule reference
- Published docs site: https://eriyc.github.io/rules_bun/
- Generated API docs: docs/rules.md
- Regenerate:
bazel build //docs:rules_md && cp bazel-bin/docs/rules.md docs/rules.md
Use
These steps show how to consume a tagged release of rules_bun in a separate Bazel workspace.
1) Add the module dependency
In your project's MODULE.bazel, add:
bazel_dep(name = "rules_bun", version = "0.1.0")
archive_override(
module_name = "rules_bun",
urls = ["https://github.com/Eriyc/rules_bun/archiv0.0.5.tar.gz"],
strip_prefix = "rules_bun-v0.1.0",
)
For channel/pre-release tags (for example v0.1.0-rc.1), use the matching folder prefix:
bazel_dep(name = "rules_bun", version = "0.1.0-rc.1")
archive_override(
module_name = "rules_bun",
urls = ["https://github.com/Eriyc/rules_bun/archiv0.0.5-rc.1.tar.gz"],
strip_prefix = "rules_bun-v0.1.0-rc.1",
)
Note: keep the v prefix in the Git tag URL and strip_prefix; for bazel_dep(..., version = ...), use the module version string without the leading v.
2) Create Bun repositories with the extension
Still in MODULE.bazel, add:
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_linux_x64",
"bun_linux_aarch64",
"bun_darwin_x64",
"bun_darwin_aarch64",
"bun_windows_x64",
)
3) Register toolchains
Also in MODULE.bazel, register:
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",
)
4) Load rules in BUILD.bazel
load(
"@rules_bun//bun:defs.bzl",
"bun_binary",
"bun_bundle",
"bun_dev",
"bun_script",
"bun_test",
"js_library",
"ts_library",
)
5) (Optional) Use bun_install module extension
If you want Bazel-managed install repositories, add:
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install(
name = "npm",
package_json = "//:package.json",
bun_lockfile = "//:bun.lock",
)
use_repo(bun_install_ext, "npm")
6) Verify setup
Run one of your bun-backed targets, for example:
bazel test //path/to:your_bun_test
All rules_bun rule-driven Bun invocations pass --bun.
Package scripts (bun_script)
Use bun_script to expose a package.json script as a Bazel executable target.
load("@rules_bun//bun:defs.bzl", "bun_script")
bun_script(
name = "web_dev",
script = "dev",
package_json = "package.json",
node_modules = "@npm//:node_modules",
data = glob([
"src/**",
"static/**",
"vite.config.*",
"svelte.config.*",
"tsconfig*.json",
]),
)
Run it with:
bazel run //path/to:web_dev -- --host
bun_script defaults to running from the directory containing package.json, which matches the usual expectations for vite, svelte-kit, and similar package scripts.
Development mode (bun_dev)
Use bun_dev for long-running local development with Bun watch mode.
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",
)
Run it with:
bazel run //path/to:web_dev
bun_dev supports:
watch_mode = "watch"(default) forbun --watchwatch_mode = "hot"forbun --hotrestart_on = [...]to force full process restarts when specific files changeworking_dir = "workspace" | "entry_point"(default:workspace)
Runtime working directory (bun_binary, bun_dev)
bun_binary and bun_dev support working_dir:
"workspace"(default): runs from the Bazel runfiles workspace root."entry_point": runs from the nearest ancestor of the entry point that contains.envorpackage.json(falls back to the entry point directory).
Use "entry_point" when Bun should resolve local files such as colocated .env files relative to the program directory.
Hybrid Go + Bun + protobuf workflow
For monorepos that mix Go and Bun (including FFI):
- Run Bun app with native watch/HMR via
bun_dev. - Put generated artifacts or bridge files in
restart_on(for example generated JS/TS files from proto/go steps). - Rebuild Go/proto artifacts separately (for example with
ibazel build) so their output files change. bun_devdetects thoserestart_onchanges and restarts Bun, while ordinary JS edits continue to use Bun watch/HMR without full Bazel restarts.
This keeps the fast Bun JS loop while still supporting full restarts when non-JS dependencies change.