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 Johnjs_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). |