> ## Documentation Index
> Fetch the complete documentation index at: https://site.aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript with Bazel

> Build JavaScript and TypeScript with Bazel using rules_js, rules_ts, pnpm workspaces, Jest, esbuild, webpack, and Next.js integrations.

Bazel gives JavaScript and TypeScript projects fast, incremental builds with correct caching, even across large monorepos with hundreds of packages.
Its hermetic build engine guarantees reproducibility for teams that need reliability at scale.

<Tip>
  Stuck?

  * Check for [known issues](https://github.com/aspect-build/rules_js/issues)
  * Ask in `#javascript` on [Bazel Slack](http://slack.bazel.build)
  * Sign up for [commercial support](/services), provided by Aspect as a shared Slack channel.
</Tip>

## Create a new project

<Steps>
  <Step title="Install the Aspect CLI.">
    ```bash theme={null}
    brew install aspect-build/aspect/aspect
    ```

    For more details, see [Aspect CLI](/docs/cli). `aspect init` requires CLI v2026.25.11 or newer.
  </Step>

  <Step title="Scaffold a new project.">
    ```bash theme={null}
    aspect init my-app --preset js && cd my-app
    ```

    A working Bazel + JS/TS setup: pnpm workspaces, `rules_js`, `rules_ts`, and Gazelle-generated BUILD files. See [`aspect init`](/docs/cli/tasks/init) for the full flag reference (presets, `--template`, `--license`).

    Prefer GitHub's "Use this template" button? Start from [aspect-starters/js](https://github.com/aspect-starters/js) instead, or `git clone https://github.com/aspect-starters/js my-app`.
  </Step>
</Steps>

## Explore Bazel

<Columns cols={2}>
  <Card title="Starter Template" icon="clone" href="https://github.com/aspect-starters/js">
    If you just want the code, clone the starter repository and explore a working Bazel + JS/TS setup immediately.

    Use GitHub's Codespace for an instant playground.
  </Card>

  <Card title="Bazel 105: JS & TS Training" icon="graduation-cap" href="/learning/bazel-105">
    A hands-on course for building, testing, and shipping JS and TS with Bazel.

    Covers `pnpm`, TypeScript, `esbuild`, Vite, and more.
  </Card>
</Columns>

## Package management with pnpm

`rules_js` consumes a pnpm-lock.yaml lockfile to create a correct `node_modules` tree.
Unlike `npm` or `yarn` lockfiles, `pnpm's` lockfile format is expressive enough for Bazel to resolve the dependency graph without ever running a package manager itself.

`rules_js` can also provide the `pnpm` binary itself, so every developer on your team uses the same version.

Aspect recommends you migrate to `pnpm` *before* adopting Bazel.

Your `.npmrc` file should include:

```ini theme={null}
hoist=false
```

See the [pnpm guide](https://github.com/aspect-build/rules_js/blob/main/docs/pnpm.md) for details.

<Tip>
  Remember to run `pnpm install` after changing `package.json`. Bazel reads directly from `pnpm-lock.yaml`, so lockfile changes won't be picked up until you update it.
</Tip>

### Automatically updating the lockfile

If you'd rather not run `pnpm install` manually, `rules_js` can update `pnpm-lock.yaml` for you. Set `update_pnpm_lock = true` in `npm_translate_lock` and Bazel runs `pnpm install` whenever its inputs change. You don't have to remember to update the lockfile and `rules_js` always uses the same version of `pnpm` from Bazel.

You can migrate from an existing `npm` or `yarn` lockfile if you haven't migrated to `pnpm` yet. Pass your `package-lock.json` or `yarn.lock` to `npm_translate_lock` with the `npm_package_lock` or `yarn_lock` attributes. When either is set, `update_pnpm_lock` defaults to `true` and `rules_js` automatically runs `pnpm import` to produce the `pnpm-lock.yaml` that Bazel needs.

However, note that when you enable `update_pnpm_lock`, you must list every `package.json` and any
other input files in the `data` attribute of `npm_translate_lock`. This tells
Bazel which files to watch so it knows when to re-run `pnpm`. In smaller projects, this list may be short and easy to maintain, but in larger monorepos, it's easy to forget to add a new file. When that happens, Bazel won't know to re-run `pnpm`, which can lead to hard-to-debug staleness issues.

See [pnpm and rules.js](https://github.com/aspect-build/rules_js/blob/main/docs/pnpm.md#update_pnpm_lock) and the [`npm_translate_lock`](https://docs.aspect.build/bazel/javascript/aspect_rules_js/npm_extensions#tag-npm_translate_lock) reference for full details.

**API reference:**
[npm extensions](/bazel/javascript/aspect_rules_js/npm_extensions) |
[npm rules](/bazel/javascript/aspect_rules_js/npm_defs)

**Troubleshooting:**
[rules\_js troubleshooting](https://github.com/aspect-build/rules_js/blob/main/docs/troubleshooting.md) |
[FAQ](https://github.com/aspect-build/rules_js/blob/main/docs/faq.md)

## Node.js programs

The `js_library`, `js_binary`, and `js_run_binary` rules let you build, test, and run JavaScript programs under Bazel.
Bazel provides a hermetic Node.js toolchain so builds aren't affected by whatever version of Node is on a developer's machine.

**API reference:**
[JavaScript rules](/bazel/javascript/aspect_rules_js/js_defs)

## Editor support

Bazel links `node_modules` under `bazel-bin/[path/to/package]/node_modules`, not in your source tree. Your editor's TypeScript server, ESLint integration, and IntelliSense don't know about `bazel-bin` — they look for a `node_modules` directory next to the `package.json`.

Run `pnpm install` in your source tree so editor tooling can resolve packages and types:

```shell theme={null}
pnpm install
```

This `node_modules` is for editor use only — Bazel ignores it and reads dependencies directly from `pnpm-lock.yaml`. Re-run `pnpm install` whenever `package.json` changes so your editor stays in sync with what Bazel builds.

<Tip>
  Keep your `.npmrc` aligned with `rules_js` by setting `hoist=false`. This makes the source-tree `node_modules` match the layout Bazel produces, so import errors reproduce identically in and out of Bazel. See [pnpm and rules\_js](/docs/bazel/javascript/pnpm_rules_js).
</Tip>

For debugger setup (VS Code launch configs, Chrome DevTools), see [Debugging](/docs/bazel/javascript/rules_js#debugging) in the `rules_js` guide.

## Protocol Buffers & gRPC

`rules_js` includes experimental support for generating JavaScript and TypeScript code from  `.proto` files which are referenced in `proto_library` targets.

1. Bring your own `protoc` plugin, such as [`@bufbuild/protoc-gen-es`](https://github.com/bufbuild/protobuf-es)
2. Configure it with a `js_proto_toolchain`
3. Reference `proto_library` targets anywhere a `js_library` can appear. Bazel invokes the code generator automatically.

**API reference:**
[Protocol Buffer rules](/bazel/javascript/aspect_rules_js/js_proto)

## Frameworks & ecosystem

Bazel works with the JavaScript tools you already use. Here are some of the integrations available:

<Columns cols={2}>
  <Card title="Next.js" icon="browser" href="/docs/bazel/javascript/aspect_rules_js/contrib_nextjs_defs">
    Bazel works with any framework, including favorites like Next.js.
  </Card>

  <Card title="Protocol Buffers & gRPC" icon="message-arrow-up" href="/docs/bazel/javascript/aspect_rules_js/js_proto">
    Generate TypeScript clients from `.proto` files using Connect.
  </Card>
</Columns>

<Columns cols={2}>
  <Card title="Bundling" icon="box-archive" href="/bazel/javascript/aspect_rules_js/js_defs#function-js_run_binary">
    Use esbuild or webpack with `js_run_binary` for production bundles.
  </Card>

  <Card title="Dev Servers" icon="play" href="/learning/bazel-105/hello-browser#running-the-devserver-under-bazel">
    Run Vite or other dev servers with live reloading under Bazel.
  </Card>
</Columns>

<Columns cols={2}>
  <Card title="Linting & Formatting" icon="check" href="/learning/bazel-105/format-and-lint">
    Integrate ESLint, Prettier, Biome, and other tools.
  </Card>

  <Card title="Container Images" icon="docker" href="/bazel/javascript/aspect_rules_js/js_defs#rule-js_image_layer">
    Package Node.js apps into OCI images with `js_image_layer` and [rules\_oci](https://github.com/bazel-contrib/rules_oci).
  </Card>
</Columns>

For more working examples, see the [Bazel examples](https://github.com/aspect-build/bazel-examples) repository.
