The State of

NgVikings 2019 — By Wassim Chegham

The State of

Angular Tooling

Angular Tooling

Building a better Developer Experience​:

Angular 6—7—8

@ManekiNekko

Angular Ecosystem!

Microsoft

Sr. Developer Advocate

Wassim Chegham

Klingon

(author)

xLayers.dev

(author)

Angular Tooling Team

Compodoc

(co-author)

Universal

(former member)

angular console

(former member)

ngx.tools

(author)

Google Cloud

Actions On Google

Angular

GDE–nominated by GOOGLE

THANK YOU 💕

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

Validate Inputs: schema.json

{
  "$schema": "http://json-schema.org/schema",
  "type": "object",
  "properties": {
    "command": {
      "type": "string"
    },
    "args": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  }
}

@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

Schematics

When accessing the filesystem...

ng generate, update, add

When extending the CLI build workflow...

ng build, test, lint, serve, deploy

Builders

@ManekiNekko

Telemetry

Telemetry

Build Telemetry

Share usage data with the Angular team 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

polyglot

@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

built with

@ManekiNekko

@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

Ready for Ivy?

Smaller bundles size

Faster compilation

Simpler stack traces

Non-Breaking Changes!!!!!!

@ManekiNekko

Opting into Angular Ivy in version 8

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

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