Bazel For

Wassim Chegham presents

Angular 

Developers

Bazel For

"The Rest Of Us".

Microsoft

Senior Developer Advocate

WassimChegham

Klingon

(author)

xLayers.dev

(author)

Angular Core Team

Compodoc

(co-author)

Universal

(former member)

angular console

(former member)

ngx.tools

(author)

Node.js Foundation Invited Member

A Fun Journey Into Bazel   Internals.

the problem?

the frontend build process is broken!

@ManekiNekko

–"the build time is proportional to the numbers of files."

@ManekiNekko

–"why is it taking ages to rebuild my changes?"

@ManekiNekko

–"it builds on my machine but why the ci is red?"

@ManekiNekko

HOW can we fix this?

–"the build time is proportional to the numbers of changes."

@ManekiNekko

–"my changes take 2 seconds* to rebuild!"

@ManekiNekko

* that is our goal

–"it builds everywhere."

@ManekiNekko

Bazel.

Bazel: A modern build and test orchestration system.

@ManekiNekko

Bazel isn't replacing Webpack nor the CLI nor any other build tool.

Disclaimer

@ManekiNekko

Benefits of Bazel

incremental

deterministic

Hermetic

composable

industrial grade

@ManekiNekko

Universally Fullstack

Android, C & C++, C#, D, Docker, Go, Groovy, Kotlin, iOS, Java, JavaScript, Jsonnet, Objective, OCaml, C, Proto Buffers, Python, Rust, Sass, Scala, Shell, TypeScript, etc...

@ManekiNekko

they use bazel

bazel concepts.

is A folder containing the source files of your project and has a file named "WORKSPACE".

workspacepackagetargetlabelruleaction

@ManekiNekko

@angular_bazel_example// on master and ⬢ v10.15.3
➜ ls -l
total 512
-rw-r--r--   1 wassimchegham  staff     469 Apr 23 18:21 BUILD.bazel
-rw-r--r--   1 wassimchegham  staff    1096 Apr 23 18:21 LICENSE
-rw-r--r--   1 wassimchegham  staff    7814 Apr 23 18:21 README.md
-rw-r--r--   1 wassimchegham  staff    4706 Apr 23 18:21 WORKSPACE
-rw-r--r--   1 wassimchegham  staff    1213 Apr 23 18:21 angular-metadata.tsconfig.json
-rw-r--r--   1 wassimchegham  staff    2391 Apr 23 18:21 angular.json
-rw-r--r--   1 wassimchegham  staff     429 Apr 23 18:21 deployment.yaml
drwxr-xr-x   5 wassimchegham  staff     160 Apr 23 18:21 e2e
-rw-r--r--   1 wassimchegham  staff    3480 Apr 23 18:21 package.json
-rw-r--r--   1 wassimchegham  staff      41 Apr 23 18:21 renovate.json
drwxr-xr-x  17 wassimchegham  staff     544 Apr 23 18:21 src
drwxr-xr-x   3 wassimchegham  staff      96 Apr 23 18:21 tools
-rw-r--r--   1 wassimchegham  staff  215262 Apr 23 18:21 yarn.lock

workspacepackagetargetlabelruleaction

@ManekiNekko

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 = "213dcf7e72f3acd4d1e369b7a356f3e5d9560f380bd655b13b7c0ea425d7c419",
    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.27.9/rules_nodejs-0.27.9.tar.gz"],
)

# Load rule definition
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version")

# Invoke rule
check_bazel_version(...)

# 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()

workspacepackagetargetlabelruleaction

The primary unit of code organization in a workspace. A folder containing a file named

"BUILD.bazel".

workspacepackagetargetlabelruleaction

@ManekiNekko

bazel package

one build file per directory

workspacepackagetargetlabelruleaction

@ManekiNekko

@angular_bazel_example// on master and ⬢ v10.15.3
➜ find ./ -iname BUILD.bazel
.//BUILD.bazel
.//e2e/BUILD.bazel
.//src/app/home/BUILD.bazel
.//src/app/networking/BUILD.bazel
.//src/app/networking/module0/BUILD.bazel
.//src/app/networking/module1/BUILD.bazel
.//src/app/hello-world/BUILD.bazel
.//src/app/storage/BUILD.bazel
.//src/app/storage/module0/BUILD.bazel
.//src/app/storage/module1/BUILD.bazel
.//src/app/datastore/BUILD.bazel
.//src/app/datastore/module0/BUILD.bazel
.//src/app/datastore/module1/BUILD.bazel
.//src/app/compute/BUILD.bazel
.//src/app/compute/module0/BUILD.bazel
.//src/app/compute/module1/BUILD.bazel
...

workspacepackagetargetlabelruleaction

load("@npm_angular_bazel//:index.bzl", "ng_module")

package(default_visibility = ["//:__subpackages__"])

ng_module(
    name = "billing",
    srcs = [
        "billing.module.ts",
        "index/index.component.ts",
    ],
    assets = [
        "index/index.component.html",
    ],
    tsconfig = "//src:tsconfig.json",
    deps = [
        "//src/app/billing/module0",
        "//src/app/billing/module1",
        "@npm//@angular/common",
        "@npm//@angular/core",
        "@npm//@angular/router",
    ],
)

workspacepackagetargetlabelruleaction

angular module

BAZEL PACKAGE*

* keep packages fine-grained

workspacepackagetargetlabelruleaction

@ManekiNekko

a set of directives defined in a package.

workspacepackagetargetlabelruleaction

@ManekiNekko

files.

rules.

package group.

written.

generated.

can be...

workspacepackagetargetlabelruleaction

@ManekiNekko

a globally unique identifier of a target.

workspacepackagetargetlabelruleaction

@ManekiNekko

@angular\_bazel\_example

Workspace Name

Package

Target

src/app/billing
:billing
//

Workspace Root

workspacepackagetargetlabelruleaction

@ManekiNekko

@angular\_bazel\_example//src/app/billing:billing
//src/app/billing:billing
//src/app/billing
:billing
billing

workspacepackagetargetlabelruleaction

@ManekiNekko

the relationship between inputs and outputs, and the steps to build the outputs.

workspacepackagetargetlabelruleaction

@ManekiNekko

binary.

Test.

library.

*_binary()

can be...

*_test()

*_library()

workspacepackagetargetlabelruleaction

@ManekiNekko

# //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

workspacepackagetargetlabelruleaction

workspacepackagetargetlabelruleaction

@angular/core/**/*.ts

rollup_bundle()

./core.js

./core.d.ts

 ts_library()

./bundles/core.umd.js

@ManekiNekko

how to generate a set of outputs from a set of inputs.

workspacepackagetargetlabelruleaction

@ManekiNekko

Action(x)=y

workspacepackagetargetlabelruleaction

@ManekiNekko

workspacepackagetargetlabelruleaction

ts_library()

tsc -p name_tsconfig.json

@ManekiNekko

Evaluation model.

LoadingAnalysisExecution

load and evaluate all extensions and all BUILD files that are needed for the build.

@ManekiNekko

LoadingAnalysisExecution

the analysis phase takes the graph generated by the loading phase and generates an action graph.

@ManekiNekko

LoadingAnalysisExecution

Actions are executed.

 

Tests are also run during this phase.

@ManekiNekko

action

action

action

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

@ManekiNekko

Bazel execution Graph

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

@ManekiNekko

Bazel execution Graph

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

@ManekiNekko

Bazel execution Graph

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

ACTION

Bazel execution Graph

@ManekiNekko

Bazel Cache

sha1

sha1

sha1

sha1

sha1

sha1

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

Bazel Cache

sha1

sha1

sha1

sha1

sha1

sha1

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

Bazel Cache

sha1

sha1

sha1

sha1

sha1

sha1

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

Bazel Cache

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

sha1

sha1

sha1

sha1

sha1

sha1

Local Cache & Execution

code

local bazel's cache

local bazel execution

@ManekiNekko

code

remote bazel's cache

remote bazel execution

dynamic bazel execution

Remote Cache & execution

@ManekiNekko

Real "Entreprise-y" Application

Use with the Angular CLI*

# For new apps
npm install -g @angular/bazel
ng new my-app --collection=@angular/bazel

# For existing apps
ng add @angular/bazel

*Experimental

@ManekiNekko

installing bazel

npm i -g @bazel/bazel

bazel build //src:bundle
bazel run @nodejs//:npm
basel test ...

# Install from https://bazel.build.

@ManekiNekko

bazel setup and configuration will be transparent to users, and you should not need to learn Bazel.

 

good news for angular!!

Microsoft

Senior. Developer Advocate

WassimChegham

dev.to/angular