Slide 1

Slide 1 text

ngular Minko Gechev github.com/mgechev twitter.com/mgechev blog.mgechev.com toolset support (extended) https://flic.kr/p/fipdcK

Slide 2

Slide 2 text

github.com/mgechev twitter.com/mgechev blog.mgechev.com About deprecated

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Hold on for the second edition!

Slide 5

Slide 5 text

agenda

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

What’s Angular?

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Here Here Here

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

Angular Tooling • Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers

Slide 22

Slide 22 text

• Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers Angular Tooling

Slide 23

Slide 23 text

• Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers Angular Tooling

Slide 24

Slide 24 text

• Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers Angular Tooling

Slide 25

Slide 25 text

• Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers Angular Tooling

Slide 26

Slide 26 text

• Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers Angular Tooling

Slide 27

Slide 27 text

• Angular’s AoT compiler • TypeScript compiler • Testing • Unit testing • e2e testing • Coverage • Module loader • Bundler • Provides bundling and tree shaking • Linter • TypeScript and CSS • Minifier • Minification & deadcode elimination • Service workers management/generation Angular Tooling

Slide 28

Slide 28 text

Where to start? https://flic.kr/p/pcf4cU

Slide 29

Slide 29 text

angular-cli

Slide 30

Slide 30 text

ng new hello-world

Slide 31

Slide 31 text

angular-cli • Quick bootstrap of projects • Scaffolding of: • Components • Services • … • Uses Webpack • Support for mobile toolkit, material, etc.

Slide 32

Slide 32 text

# serves the application ng serve # generate new component ng g component my-new-component # build an app with env config ng build --prod --env=prod ng build --dev --env=dev CLI 101

Slide 33

Slide 33 text

angular-seed

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

@ludohenin @TheDonDope @d3viant0ne @Shyam-Chen @NathanWalker

Slide 38

Slide 38 text

git clone [email protected]/mgechev/angular-seed

Slide 39

Slide 39 text

angular-seed • Modular statically typed build • Multiple apps in the same project • Well maintained & easy to update • AoT compilation support • Unit & e2e testing • Test coverage • tslint and codelyzer

Slide 40

Slide 40 text

# build & start the dev server npm start # test the app npm t # build with env config npm run build.prod --env-config custom # build with AoT npm run build.prod.exp Seed 101

Slide 41

Slide 41 text

Other starters • angular2-webpack-starter • Webpack based • angular2-seed-advanced • NativeScript, Electron, etc. • Based on angular-seed

Slide 42

Slide 42 text

Development process and experience https://flic.kr/p/daxeMY

Slide 43

Slide 43 text

Typical JavaScript experience

Slide 44

Slide 44 text

Angular is… • Built with TypeScript • Designed with tooling in mind

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

We already have • Superset of JavaScript • Compile time type checking

Slide 47

Slide 47 text

Analyzable templates https://flic.kr/p/irHwLW

Slide 48

Slide 48 text

Angular 1

Slide 49

Slide 49 text

Angular 1

Slide 50

Slide 50 text

Angular 1

Slide 51

Slide 51 text

Angular 1

Slide 52

Slide 52 text

Angular 2

Slide 53

Slide 53 text

Angular 2

Slide 54

Slide 54 text

Angular 2 Component @Component({ selector: 'hero-details', template: `

Age: {{ formatAge(hero.age) }} ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }

Slide 55

Slide 55 text

Does property exist @Component({ selector: 'hero-details', template: `

Age: {{ formatAge(hero.age) }} ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }

Slide 56

Slide 56 text

Type checking @Component({ selector: 'hero-details', template: `

Age: {{ formatAge(hero.age) }} ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }

Slide 57

Slide 57 text

Advanced type checking @Component({ selector: 'hero-details', template: `

Age: {{ formatAge(hero.age) }} ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }

Slide 58

Slide 58 text

github.com/mgechev/ codelyzer

Slide 59

Slide 59 text

“Codelyzer contains set of rules that provide automated alignment to the Angular Style Guide & improvement of our development experience”

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

Why not instant feedback*

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

Trusted by • Angular team • jQWidgets • ng2-bootstrap

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

Language Service • Syntax highlighting in templates • Syntax and semantic error reporting • Auto-completion in templates

Slide 67

Slide 67 text

AoT compilation

Slide 68

Slide 68 text

How Angular works?

Slide 69

Slide 69 text

Disclaimer The description is simplified and does not completely align with the actual implementation.

Slide 70

Slide 70 text

component.ts import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `

Hello {{ name }}!

Summary of the awesome app!

` }) export class Component { name: string; }

Slide 71

Slide 71 text

interface InternalComponent { create(); detectChanges(); destroy(); } internal-component.ts For more information: http://bit.ly/2dsk6z5

Slide 72

Slide 72 text

class InternalComponent { create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!')); } //... } create method

Slide 73

Slide 73 text

class InternalComponent { create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!')); } //... } create method

Hello {{ name }}!

Summary of the awesome app!

Slide 74

Slide 74 text

class InternalComponent { create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!')); } //... } create method

Hello {{ name }}!

Summary of the awesome app!

Slide 75

Slide 75 text

class InternalComponent { create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!')); } //... } create method

Hello {{ name }}!

Summary of the awesome app!

Slide 76

Slide 76 text

class InternalComponent { create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!')); } //... } create method

Hello {{ name }}!

Summary of the awesome app!

Slide 77

Slide 77 text

class InternalComponent { create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!')); } //... } create method

Slide 78

Slide 78 text

const template = `

Hello {{ name }}!

Summary of the awesome app!

`; header h1 p TextNode TextNode Interp Expr Template to AST

Slide 79

Slide 79 text

header h1 p TextNode TextNode Interp Expr create() this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

Slide 80

Slide 80 text

header h1 p TextNode TextNode Interp Expr create() this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

Slide 81

Slide 81 text

header h1 p TextNode TextNode Interp Expr create() this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

Slide 82

Slide 82 text

this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

header h1 p TextNode TextNode Interp Expr create()

Slide 83

Slide 83 text

this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

header h1 p TextNode TextNode Interp Expr create()

Slide 84

Slide 84 text

this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

header h1 p TextNode TextNode Interp Expr create()

Slide 85

Slide 85 text

this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

header h1 p TextNode TextNode Interp Expr create()

Slide 86

Slide 86 text

this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); this.p = r.createElement(this.header, 'p'); r.createText(this.p, 'Summary of the awesome app!'));

Hello {{ name }}!

Summary of the awesome app!

header h1 p TextNode TextNode Interp Expr create()

Slide 87

Slide 87 text

detectChanges() class InternalComponent { //... detectChanges() { let val = interpolate('Hello', this.context.name, '!'); if (this.binding !== val) { r.createText(this.h1, val); this.binding = val; } } //... }

Slide 88

Slide 88 text

You can bind ONLY to public members

Slide 89

Slide 89 text

What about encapsulation

Slide 90

Slide 90 text

encapsulation tsc demo.component.ts --stripInternal TypeScript will omit name from the d.ts files @Component({ selector: 'my-app', template: `...` }) export class Component { /** @internal */ name: string = 'Iron Man'; }

Slide 91

Slide 91 text

--stripInternal import { Component } from 'library'; const cmp = new Component(); // Property 'name' does not exist on type 'Component'. cmp.name = 'Captain America';

Slide 92

Slide 92 text

Why do we need to generate detectChanges?

Slide 93

Slide 93 text

Scope.prototype.$digest = function () { 'use strict'; var dirty, watcher, current, i; do { dirty = false; for (i = 0; i < this.$$watchers.length; i += 1) { watcher = this.$$watchers[i]; current = this.$eval(watcher.exp); if (!Utils.equals(watcher.last, current)) { watcher.last = Utils.clone(current); dirty = true; watcher.fn(current); } } } while (dirty); for (i = 0; i < this.$$children.length; i += 1) { this.$$children[i].$digest(); } }; Traditional CD http://bit.ly/2dS0d7P

Slide 94

Slide 94 text

CD with codegen • Easier to reason about • Obviously fast • Inline caching performance boost • VM friendly code

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

If the codegen happens at build time, it’s called AoT; if it happens at runtime, it’s called JiT

Slide 97

Slide 97 text

AoT Brings • Easy drop of unused components in bundle • Code which is easy for dead-code elimination • Fast initial rendering • Components are distributed pre-compiled • Allows us to drop compiler from bundler • We compile ahead of time so we don’t need it runtime

Slide 98

Slide 98 text

import { interpolate, Renderer, ... } from "…"; ... create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); //... } ... vs

Hello {{ name }}!

Summary of the awesome app!

Slide 99

Slide 99 text

import { interpolate, Renderer, ... } from "…"; ... create() { this.header = r.createElement('header'); this.h1 = r.createElement(this.header, 'h1'); this.binding = interpolate('Hello', this.context.name, '!'); r.createText(this.h1, this.binding); //... } ...

Hello {{ name }}!

Summary of the awesome app!

vs

Slide 100

Slide 100 text

AoT generated code has explicit imports so the bundler knows what the app uses

Slide 101

Slide 101 text

Introducing ngc

Slide 102

Slide 102 text

./node_modules/.bin/ngc -p tsconfig.json

Slide 103

Slide 103 text

ngc is a wrapper over tsc

Slide 104

Slide 104 text

ngc will produce • *.ngfactory.ts • *.css.shim.ts • *.metadata.json

Slide 105

Slide 105 text

*.ngfactory.ts contains the “internal components” we described

Slide 106

Slide 106 text

*.css.shim.ts contains the scoped component styles

Slide 107

Slide 107 text

*.metadata.json contains component metadata (i.e., Angular specific decorators)

Slide 108

Slide 108 text

{ "decorators": [{ "expression": { "__symbolic": "reference", "module": "@angular/core", "name": "Component" }, "arguments": [{ "selector": "sd-app", "templateUrl": "app.html" }] }] } @Component({ selector: 'sd-app', templateUrl: 'app.html', }) export class AppComponent {} app.ts *app.metadata.json

Slide 109

Slide 109 text

ngc compatible third-party libraries must be distributed with *.metadata.json

Slide 110

Slide 110 text

AoT compiled application has a slightly different bootstrap mechanism

Slide 111

Slide 111 text

JiT bootstrap import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);

Slide 112

Slide 112 text

import { platformBrowser } from '@angular/platform-browser'; import { AppModuleNgFactory } from './app.module.ngfactory'; platformBrowser().bootstrapModule(AppModule); JiT bootstrap AoT bootstrap import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

Resources • Angular CLI • AoT in Angular 2 • Building an Angular 2 Application for Production • 2.5X Smaller Angular 2 Apps with GCC • Codelyzer

Slide 115

Slide 115 text

mgv.io/ngtool-feedback

Slide 116

Slide 116 text

Thank you! github.com/mgechev twitter.com/mgechev blog.mgechev.com