Wassim Chegham PRO
Senior Developer Advocate @Microsoft ★ Angular contributor ★ Bazel contributor ★ GDE @Google ★ creator of @itsjustangular / hueaction.dev / ngx.tools / xlayers.dev / angular.run / thundr.dev
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.bazel
tsc 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.bzl
script_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.png
dev.to/wassimchegham
dev.to/angular
dev.to/bazel
By Wassim Chegham
This is a full introduction to Bazel, the orchestration build and test tool. We will cover the concepts of Bazel such as Workspaces, Packages, and Labels, as well as writing custom rules. We will demo how to build a WASM code written in Rust and deploy it on Azure Functions.
Senior Developer Advocate @Microsoft ★ Angular contributor ★ Bazel contributor ★ GDE @Google ★ creator of @itsjustangular / hueaction.dev / ngx.tools / xlayers.dev / angular.run / thundr.dev