Supercharge your builds with Bazel
Wassim Chegham
#Always_Bet_On_JavaScript
I love open source...
hexa.run
angular.run
xLayers.dev
nitr.ooo
ngx.tools
@rules_nodejs// on master and ⬢ v13.7.0
➜ find ./ -iname "WORKSPACE"
.//WORKSPACE
.//examples/angular/WORKSPACE
.//examples/kotlin/WORKSPACE
.//examples/angular_view_engine/WORKSPACE
.//examples/nestjs/WORKSPACE
.//packages/labs/src/WORKSPACE
.//packages/typescript/src/WORKSPACE
.//packages/karma/src/WORKSPACE
.//packages/rollup/src/WORKSPACE
.//packages/terser/src/WORKSPACE
.//packages/jasmine/src/WORKSPACE
.//packages/protractor/src/WORKSPACE
.//e2e/jasmine/WORKSPACE
...workspace(name = "angular_bazel_example")
# This rule is built-into Bazel but we need to load it first to download more rules
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
# Fetch rule implementation as an archive
http_archive(
    name = "build_bazel_rules_nodejs",
    sha256 = "9473b207f1c5a61b603442cbfeeea8aaf2aa62870673fce2a1c52087f6ff4dc9",
    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.2.4/rules_nodejs-1.2.4.tar.gz"],
)
# Load rule definition
load("@build_bazel_rules_nodejs//:index.bzl", "npm_install")
# Invoke rule
npm_install(
    name = "npm",
    package_json = "//:package.json",
    package_lock_json = "//:package-lock.json"
)
# Fetch rule implementation from a GIT repo
git_repository(
    name = "io_bazel_rules_k8s",
    commit = "d72491924369868a13532af9f15cb766e5943855",
    remote = "https://github.com/bazelbuild/rules_k8s.git",
)
# Load rule definition
load("@io_bazel_rules_k8s//k8s:k8s.bzl", "k8s_defaults")
# Invoke rule
k8s_repositories()
@rules_nodejs// on master and ⬢ v13.7.0
➜ find ./ -iname "BUILD.bazel"
./internal/BUILD.bazel
./internal/linker/test/BUILD.bazel
./internal/linker/BUILD.bazel
./internal/pkg_npm/test/BUILD.bazel
./internal/pkg_npm/BUILD.bazel
./internal/golden_file_test/BUILD.bazel
./internal/providers/BUILD.bazel
./internal/js_library/BUILD.bazel
./internal/common/test/BUILD.bazel
./internal/common/BUILD.bazel
./internal/bazel_integration_test/BUILD.bazel
./internal/node/test/lib1/BUILD.bazel
./internal/node/test/BUILD.bazel
...package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary")
load("@io_bazel_rules_rust//wasm_bindgen:wasm_bindgen.bzl", "rust_wasm_bindgen")
rust_binary(
    name = "hello_world_rust",
    srcs = ["main.rs"],
    edition = "2018",
    deps = [
        "@io_bazel_rules_rust//wasm_bindgen/raze:wasm_bindgen"
    ]   
)
rust_wasm_bindgen(
    name = "hello_world_bindgen",
    wasm_file = ":hello_world_rust",
    bindgen_flags = ["--nodejs"]
)
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary")
load("@io_bazel_rules_rust//wasm_bindgen:wasm_bindgen.bzl", "rust_wasm_bindgen")
rust_binary(
    name = "hello_world_rust",
    srcs = ["main.rs"],
    edition = "2018",
    deps = [
        "@io_bazel_rules_rust//wasm_bindgen/raze:wasm_bindgen"
    ]   
)
rust_wasm_bindgen(
    name = "hello_world_bindgen",
    wasm_file = ":hello_world_rust",
    bindgen_flags = ["--nodejs"]
)
Workspace name
Package
Target
Workspace Root
# //src/lib/shorten/BUILD.bazel
ts_library(
    name = "shorten",
    srcs = ["shorten.ts"],
    module_name = "@bazel/shorten",
    module_root = "shorten",
    deps = [
        "//some/dep",
        "@npm//other/dep",
    ],
)
# Output: 
# - shorten.d.ts
# - shorten.js@angular/core/**/*.ts
./core.js
./core.d.ts
./bundles/core.umd.js
ts_library()
rollup_bundle()
tsc -p tsconfig.json ...
ts_library()
def fizz_buzz(n):
  """Print Fizz Buzz numbers from 1 to n."""
  for i in range(1, n + 1):
    s = ""
    if i % 3 == 0:
      s += "Fizz"
    if i % 5 == 0:
      s += "Buzz"
    print(s if s else i)
fizz_buzz(20)NO: class, import, while, yield, lambda and nested functions, try, raise, except, finally...
Starlark’s syntax is inspired by Python3
# index.bzl
def _empty_impl(ctx):
    print("This rule does nothing")
empty = rule(implementation = _empty_impl)
#-----------------------------------------
# BUILD.bazel
load("//:index.bzl", "empty")
empty(name = "nothing")$ bazel build //:nothing$ ls
.
├── WORKSPACE
├── index.bzl
└── BUILD.bazeltsc file-1.ts file-2.ts  \
    --target es6 \
    --outFile main.bundle.js# WORKSPACE
workspace(name = "tsc_binary_example")
# BUILD.bazel
load("//:index.bzl", "tsc_binary")
tsc_binary(
    name = "bazel_tsc",
    srcs = [
        ":file-1.ts",
        ":file-2.ts"
    ],
)
# index.bzl
# See next slide...$ tree 
.
├── WORKSPACE
├── BUILD
├── file-1.ts
├── file-2.ts
└── index.bzlscript_template = """\
#!/bin/bash
tsc {ts_files} --target es6 --outFile {out_file}
"""
def _tsc_binary_impl(ctx):
    output = ctx.actions.declare_file("%s.sh" % ctx.label.name)
    script_content = script_template.format(
        out_file = "%s.bundle.js" % output.short_path,
        ts_files = " ".join([f.path for f in ctx.files.srcs]),
    )
   
    # tsc file-1.ts file-2.ts --target es6 --outFile bazel_tsc.sh.bundle.js
    ctx.actions.write(output, script_content, is_executable = True)
    runfiles = ctx.runfiles(files = ctx.files.srcs)
    return [DefaultInfo(executable = output, runfiles = runfiles)]
tsc_binary = rule(
    implementation = _tsc_binary_impl,
    attrs = {
        "srcs": attr.label_list(
            allow_files = True,
            doc = "Input TypeScript files",
        ),
    },
    executable = True,
)
* Needs to be configured separately! (https://docs.bazel.build/versions/main/remote-execution-ci.html)
bazel query 'deps(//...)' --output graph | dot -Tpng > docs/graph.pngdev.to/wassimchegham
dev.to/angular
dev.to/bazel