The State of

By Wassim Chegham

The State of

Angular Tooling

Angular Tooling

Microsoft

Senior Cloud Advocate

Wassim Chegham

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

Building a better Developer Experience​:

Angular 6—7—8

@ManekiNekko

Angular Ecosystem!

npm i -g

@angular/cli

Schematics

Schematics: Blueprints for the CLI

Default

Extend

Replace

custom

@ManekiNekko

Create your own Schematic

npm install -g @angular-devkit/schematics-cli
schematics blank --name=foo   

CREATE /foo/README.md (639 bytes)
CREATE /foo/.gitignore (191 bytes)
CREATE /foo/.npmignore (64 bytes)
CREATE /foo/package.json (540 bytes)
CREATE /foo/tsconfig.json (656 bytes)
CREATE /foo/src/collection.json (205 bytes)
CREATE /foo/src/foo/index.ts (310 bytes)
CREATE /foo/src/foo/index_spec.ts (456 bytes)

@ManekiNekko

Use your own Schematic

ng new my-foo-app && cd $_
npm link /path/to/foo 

schematics <path>:<schematic> --<option>=<value>

# schematics .:foo --tests=false

@ManekiNekko

The Builder API

The Builder API is the Angular Tooling system to develop and interact with Builders and external tools, which can perform common tasks: Linting, Building...

"

@ManekiNekko

Tooling api

Builders api

@angular-devkit/architect

deploy... xyz

cli, GUI... xyz

The Builder API: Why?

@ManekiNekko

import { 
  BuilderOutput, 
  createBuilder 
} from '@angular-devkit/architect';

export default createBuilder((options, context) => {
  return new Promise<BuilderOutput>(resolve => {
    resolve({ success: true });
  });
});

Create a Builder

@ManekiNekko

Package it: builders.json

{
  "builders": {
    "command": {
      "implementation": "./command",
      "schema": "./command/schema.json",
      "description": "Runs any command line in the operating system."
    }
  }
}

@ManekiNekko

The Builder Package

{
  "name": "@example/command-runner",
  "version": "1.0.0",
  "description": "Builder for Architect",
  "builders": "builders.json",
  "devDependencies": {
    "@angular-devkit/architect": "^1.0.0"
  }
}

@ManekiNekko

Use The Builder: angular.json

{
  "projects": {
    "builder-test": {
      "architect": {
        "touch": {
          "builder": "@example/command-runner:command",
          "options": {
            "command": "touch",
            "args": [
              "src/main.ts"
            ]
          }
        },
      }
    }
  }
}
ng run @command-runner:command

@ManekiNekko

Builder Examples & Resources

Telemetry

Telemetry

Build Telemetry

Share usage data with the Angular team or your internal Analytics server in order to improve the CLI (read more).

"

@ManekiNekko

Build Telemetry: Metrics/Dim.

ng commands & flags,

Node Version,

Build Time & Errors,

RAM & CPU usage,

Artifacts size...

Read more.

@ManekiNekko

⚠️Build Telemetry: Opt-IN ⚠️

Opt-in and opt-out at any time

Disabled by default

Must be enabled at the project level

@ManekiNekko

Build Telemetry: CI

When running in a CI env, Use NG_CLI_ANALYTICS=ci

@ManekiNekko

Differential Loading

Differential Loading

Reduce the payload size for all modern browsers.

Still support legacy browser and google crawler.

On By default in version 8.

Configuration

# ./src/browserslist

> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11
# ./tsconfig.json

{
  "compilerOptions": {
    "target": "es2015"
  }
}

@ManekiNekko

Output

<!-- For modern browsers -->
<script type="module" src="polyfills-es2015.js"></script>
<script type="module" src="runtime-es2015.js"></script>
<script type="module" src="style-es2015.js"></script>
<script type="module" src="vendor-es2015.js"></script>
<script type="module" src="main-es2015.js"></script>

<!-- For Legacy browsers -->
<script nomodule src="polyfills-es5.js"></script>
<script nomodule src="runtime-es5.js"></script>
<script nomodule src="style-es5.js"></script>
<script nomodule src="vendor-es5.js"></script>
<script nomodule src="main-es5.js"></script>

@ManekiNekko

Angular Bazel

Bazel: A modern build and test orchestration system.

@ManekiNekko

Bazel isn't replacing Webpack nor the CLI.

@ManekiNekko

Disclaimer

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

@angular/core/**/*.{ts,js}

 ts_library(), ng_package(),...

./bundles/core.umd.js

Bazel Rules

@ManekiNekko

ts_library()

Bazel Actions

typescript compiler

tsc

compilation

compilation action

@ManekiNekko

Action

y
x

Bazel Actions

@ManekiNekko

Bazel Action ≈ Pure Func.

Action(x)=y

@ManekiNekko

Bazel Actions

compilation

compilation

compilation

test

package

artifact

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

Bazel's Cache

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

Bazel's Cache

@ManekiNekko

sha1

sha1

sha1

sha1

sha1

sha1

Bazel's Cache

@ManekiNekko

code

code

code

code

code

code

code

code

code

code

code

code

Bazel's Build Graph

@ManekiNekko

code

code

code

code

code

code

code

code

code

code

code

code

Bazel's Build Graph

@ManekiNekko

code

code

code

code

code

code

code

code

code

code

code

code

Bazel's Build Graph

@ManekiNekko

code

code

code

code

code

code

code

code

code

code

code

code

Bazel's Build Graph

@ManekiNekko

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

Real "Entreprise-y" Application

Use in 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

@ManekiNekko

@ManekiNekko

The state of Angular Core.

@ManekiNekko

Bonus:

Opting into Angular Ivy in version 8

ng new shiny-ivy-app --enable-ivy

GOTCHA!

AOT compilation by default!

@ManekiNekko

Goals & Benefits of Ivy

Smaller Size

Simpler Stack Traces

Faster Compilation

Non-Breaking Changes!!!!!!

@ManekiNekko

import { 
 Component
} from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <h1>{{ title }}</h1>
  `
})
export class AppComponent {
  title = 'ivy';
}
import * as tslib_1 from "tslib";
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
var AppComponent = /** @class */ (function () {
  function AppComponent() {
    this.title = 'ivy';
  }
  AppComponent.ngComponentDef = i0.ɵdefineComponent({
    type: AppComponent,
    selectors: [["app-root"]],
    factory: function AppComponent_Factory(t) {
      return new (t || AppComponent)();
    },
    consts: 2,
    vars: 1,
    template: function AppComponent_Template(rf, ctx) {
      if (rf & 1) {
        i0.ɵelementStart(0, "h1");
        i0.ɵtext(1);
        i0.ɵelementEnd();
      } if (rf & 2) {
        i0.ɵtextBinding(1, i0.ɵinterpolation1("", ctx.title, ""));
      }
    }, encapsulation: 2
  });
  AppComponent = tslib_1.__decorate([
    Component({
      selector: 'app-root',
      template: "\n\t<h1>{{ title }}</h1>    \n  "
    })
  ], AppComponent);
  return AppComponent;
}());
export { AppComponent };

Smaller Size: New Instruction Set

@ManekiNekko

Smaller Size: Tree Shakeable Features

Template Syntax

Dependency Injection

Content Projection

Structural Directives

Lifecycle Hooks

Pipes

Queries

Listeners

@ManekiNekko

36kb

7.3kb

2.7kb

Ivy minified

Ivy compressed

Today (compressed – no zone.js)

10kb

Initial target

Smaller Bundle Size 🎉

Faster Compilation

INCREMENTALITY

thanks to

LOCALITY

@ManekiNekko

Angular Elements:

Angular as Custom Elements

@ManekiNekko

HTML Templates

HTML Imports

Shadow DOM

Custom Elements

Part of the Web Components specifications

@ManekiNekko

Angular Elements: Standards-Based CE

Angular

Component

Custom

Element

@ManekiNekko

Angular

Component

Custom

Element

Angular Elements: Self Bootstrapping

@ManekiNekko

Registering Components as Custom Elements

@ManekiNekko

Use in angular.io

Stable Release

Works Everywhere

Available Now

Status & Roadmap of Elements

@ManekiNekko

WebWorkers Support

Recommended for heavy computations.

Run your own workload off the main thread.

WebWorkers: Automatic Bundling

ng generate web-worker app

CREATE tsconfig.worker.json (212 bytes)
CREATE src/app/app.worker.ts (157 bytes)
UPDATE src/tsconfig.app.json (192 bytes)
UPDATE angular.json (3893 bytes)
UPDATE src/app/app.component.ts (593 bytes)

Dynamic imports

# Before
{
  path: 'home',
  loadChildren: 'home/home.module#HomeModule'
},


# After
{
  path: 'home',
  loadChildren: () => import('home/home.module').then(m => m.HomeModule)
},

The State of Angular Tooling

Schematics for custom CLI commands.

Builders for custom CLI workflows.

Bazel for faster and scalable builds.

WebWorker for smooth UX.

Getting ready for Ivy.

Differential loading for better TTI.

Dynamic Imports FTW!

Help us by Opting-in for Telemetry 💕

Angular Future

Smaller, 

Angular Future

Smaller,

Faster,

Faster,

Easier

Easier

 @manekinekko

   slides.com/wassimchegham