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.
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 = [])
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
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 |
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 |
tsconfig |
A custom TypeScript config file (optional).
Only compiler options will be used. Some options such as
|
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 |
entry |
The path of the entrypoint within the
For example if the |
output |
The name of the JS file(s) to generate (optional). By default, the name will be |
html_template |
An HTML file template (optional). The generated JavaScript bundle will be injected with a |
mode |
Configuration mode for webpack (default 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
For example if your JavaScript files will be served from https://yourdomain.com/js/,
set |
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 See Webpack documentation for details. |
Similar to web_bundle
, but produces an executable JavaScript file (using Node).
js_script(cmd, lib)
Used to run a script (similarly to scripts
in package.json
).
Attributes | |
---|---|
cmd |
The command to run (required). |
lib |
A The script will execute in the target's compiled directory. |
js_test(cmd, lib)
Used to define a test. Arguments are identical to js_script
.
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(install, binary)
Used to invoke an NPM binary (from node_modules/.bin/[binary]
).
Attributes | |
---|---|
name |
A unique name for this rule (required). |
install |
An |
binary |
The name of the binary to execute (required). |