Loading

Bazel for Angular Developers

Wassim Chegham

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

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