bazel-javascript icon indicating copy to clipboard operation
bazel-javascript copied to clipboard

JavaScript and TypeScript rules for Bazel (React friendly)

JavaScript and TypeScript rules for Bazel

CircleCI

⚠️ Looking for new maintainers

Rules

  • js_library
  • web_bundle
  • js_binary
  • ts_library
  • js_script
  • js_test
  • npm_packages
  • npm_binary

Overview

If you're not already familiar with Bazel, install it first.

These rules allow you to set up a clean, modular and reusable build infrastructure for your JavaScript and TypeScript code.

Read through an introduction here.

Installation

First, install Bazel and Yarn.

Next, create a WORKSPACE file in your project root containing:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

# Required for access to js_library, ts_library, js_test, web_bundle, etc.
git_repository(
  name = "bazel_javascript",
  remote = "https://github.com/zenclabs/bazel-javascript.git",
  tag = "0.0.28",
)

# Required for underlying dependencies such as Node and Yarn.
git_repository(
    name = "build_bazel_rules_nodejs",
    remote = "https://github.com/bazelbuild/rules_nodejs.git",
    tag = "0.15.0",
)

load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
rules_nodejs_dependencies()

load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")

# By default, the Node and Yarn versions you have installed locally will be
# ignored, and Bazel will install a separate version instead. This helps
# achieve consistency across teams.
#
# See https://github.com/bazelbuild/rules_nodejs if you'd like to use your
# local Node and Yarn binaries instead.
node_repositories(package_json = [])

Basic example

Suppose you have the following directory structure:

[workspace]/
  WORKSPACE
  BUILD.bazel
  package.json
  yarn.lock
  src/
    BUILD.bazel
    main.js
    util/
      BUILD.bazel
      constants.js

package.json

{
  "dependencies": {
    "textbuilder": "^1.0.3"
  }
}

BUILD.bazel

package(default_visibility = ["//visibility:public"])

load("@bazel_javascript//:defs.bzl", "js_binary", "npm_packages")

js_binary(
  name = "app",
  lib = "//src:main",
  entry = "main.js",
)

npm_packages(
  name = "packages",
  package_json = ":package.json",
  yarn_lock = ":yarn.lock",
)

src/main.js

import { GREETING } from "./util/constants";

console.log(GREETING);

src/BUILD.bazel

package(default_visibility = ["//visibility:public"])

load("@bazel_javascript//:defs.bzl", "js_library")

js_library(
  name = "main",
  srcs = [
    "main.js",
  ],
  deps = [
    "//src/util:constants",
  ],
)

src/util/constants.js

import TextBuilder from "textbuilder";

const t = new TextBuilder();
t.append("Hello ", process.argv[2] || "Daniel");
export const GREETING = t.build();

src/util/BUILD.bazel

package(default_visibility = ["//visibility:public"])

load("@bazel_javascript//:defs.bzl", "js_library")

js_library(
  name = "constants",
  srcs = [
    "constants.js",
  ],
  deps = [
    "//:packages",
  ],
)

Run and build the binary:

$ bazel run //:app John
INFO: Analysed target //:app (0 packages loaded).
INFO: Found 1 target...
Target //:app up-to-date:
  bazel-bin/app.js
INFO: Elapsed time: 0.140s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action

INFO: Running command line: bazel-bin/app.js John
Hello John

Rules

js_library

js_library(
  name,
  srcs,
  deps = [],
)

Used to represent a set of JavaScript files and their dependencies.

Attributes
name

A unique name for this rule (required).

srcs

A list of source files (required).

You may include non-JavaScript files, which will be copy-pasted as is.

deps

A list of labels (optional).

This could be any other js_library targets, or at most one npm_packages target.

ts_library

ts_library(name, srcs, deps = [], tsconfig = ...)

Used to generate the compiled JavaScript and declaration files for a set of TypeScript source files.

Attributes
name

A unique name for this rule (required).

srcs

A list of source files (required).

You may include non-TypeScript files, which will be copy-pasted as is.

deps

A list of labels (optional).

This could be any other ts_library targets, or at most one npm_packages target.

tsconfig

A custom TypeScript config file (optional).

Only compiler options will be used. Some options such as paths will be overridden.

web_bundle

web_bundle(
  name,
  lib,
  entry,
  html_template,
  mode = "none",
  split_chunks = 0,
  public_path = "",
  library_name = "",
  library_target = "umd",
)

Used to compile a js_library to a JavaScript bundle to include in an HTML page.

You can run a webpack-dev-server with bazel run //target_server (append _server to your target name). Live reloading is supported if you use ibazel.

Attributes
name

A unique name for this rule (required).

lib

A js_library target (required).

entry

The path of the entrypoint within the js_library target (required).

For example if the js_library includes a single file main.js, entry should be set to "main.js".

output

The name of the JS file(s) to generate (optional).

By default, the name will be bundle.js.

html_template

An HTML file template (optional).

The generated JavaScript bundle will be injected with a <script> tag.

mode

Configuration mode for webpack (default none).

See Webpack documentation for details.

split_chunks

Whether to split the bundle into chunks.

See Webpack documentation for details.

public_path

Public path where the bundle will be served from (required if split_chunks=1).

For example if your JavaScript files will be served from https://yourdomain.com/js/, set public_path to "/js/".

library_name

The name of a library to generate (optional).

This is only necessary if you're building a JavaScript library to be used by a third-party.

See Webpack documentation for details.

library_target

The type of library to generate (default "umd"). Use along with library_name.

See Webpack documentation for details.

js_binary

Similar to web_bundle, but produces an executable JavaScript file (using Node).

js_script

js_script(cmd, lib)

Used to run a script (similarly to scripts in package.json).

Attributes
cmd

The command to run (required).

lib

A js_library target (required).

The script will execute in the target's compiled directory.

js_test

js_test(cmd, lib)

Used to define a test. Arguments are identical to js_script.

npm_packages

npm_packages(name, package_json, yarn_lock)

Used to define NPM dependencies. Bazel will download the packages in its own internal directory.

Attributes
name

A unique name for this rule (required).

package_json

A package.json file (required).

yarn_lock

A yarn.lock file (required).

npm_binary

npm_binary(install, binary)

Used to invoke an NPM binary (from node_modules/.bin/[binary]).

Attributes
name

A unique name for this rule (required).

install

An npm_packages target (required).

binary

The name of the binary to execute (required).