Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Angular Toolset Support

Minko Gechev
October 22, 2016

Angular Toolset Support

The tooling support of the modern web frameworks advances constantly. It helps us with managing boilerplates, having more efficient and automated build process. It even helps us be more consistent and confident during our development cycle, with techniques such as static code analysis! Angular is designed with tooling in mind from the beginning! Static typing, ES2015 modules and many decisions on architectural level allow development of sophisticated tools. Such tools help us be more productive during our development process. In this talk we're going to make an overview of the toolset support for Angular. We'll briefly describe Angular CLI, Codelyzer and many other projects that can be an essential part of our development workflow!

Minko Gechev

October 22, 2016
Tweet

More Decks by Minko Gechev

Other Decks in Programming

Transcript

  1. 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
  2. • 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
  3. • 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
  4. • 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
  5. • 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
  6. • 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
  7. • 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
  8. angular-cli • Quick bootstrap of projects • Scaffolding of: •

    Components • Services • … • Uses Webpack • Support for mobile toolkit, material, etc.
  9. # 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
  10. 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
  11. # 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
  12. <!-- name="hero.name + ' Avengers'" --> <user name="hero.name + '

    Avengers'"></user> <!-- name="Captain America Avengers" --> <user name="hero.name + ' Avengers'"></user> Angular 1
  13. <!-- name="Captain America Avengers" --> <user name="hero.name + ' Avengers'"></user>

    <!-- name="hero.name + ' Avengers'" --> <user name="hero.name + ' Avengers'"></user> Angular 1
  14. <!-- name="hero.name + ' Avengers'" --> <user name="hero.name + '

    Avengers'"></user> <!-- name="Captain America Avengers" --> <user [name]="hero.name + ' Avengers'"></user> Angular 2
  15. Angular 2 Component @Component({ selector: 'hero-details', template: ` <h1 [innerText]="hero.name

    + ' Avengers'"></h1> <section> Age: <span>{{ formatAge(hero.age) }}</span> </section> ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }
  16. Does property exist @Component({ selector: 'hero-details', template: ` <h1 [innerText]="hero.name

    + ' Avengers'"></h1> <section> Age: <span>{{ formatAge(hero.age) }}</span> </section> ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }
  17. Type checking @Component({ selector: 'hero-details', template: ` <h1 [innerText]="hero.name +

    ' Avengers'"></h1> <section> Age: <span>{{ formatAge(hero.age) }}</span> </section> ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }
  18. Advanced type checking @Component({ selector: 'hero-details', template: ` <h1 [innerText]="hero.name

    + ' Avengers'"></h1> <section> Age: <span>{{ formatAge(hero.age) }}</span> </section> ` }) class HeroDetailsComponent { hero: Superhero; formatAge(age: number) { // ... } }
  19. “Codelyzer contains set of rules that provide automated alignment to

    the Angular Style Guide & improvement of our development experience”
  20. Language Service • Syntax highlighting in templates • Syntax and

    semantic error reporting • Auto-completion in templates
  21. component.ts import { Component } from '@angular/core'; @Component({ selector: 'my-app',

    template: `<header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>` }) export class Component { name: string; }
  22. 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
  23. 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 <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  24. 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 <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  25. 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 <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  26. 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 <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  27. 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
  28. const template = `<header> <h1>Hello {{ name }}!</h1> <p> Summary

    of the awesome app! </p> </header>`; header h1 p TextNode TextNode Interp Expr Template to AST
  29. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  30. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  31. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  32. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header> header h1 p TextNode TextNode Interp Expr create()
  33. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header> header h1 p TextNode TextNode Interp Expr create()
  34. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header> header h1 p TextNode TextNode Interp Expr create()
  35. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header> header h1 p TextNode TextNode Interp Expr create()
  36. 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!')); <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header> header h1 p TextNode TextNode Interp Expr create()
  37. detectChanges() class InternalComponent { //... detectChanges() { let val =

    interpolate('Hello', this.context.name, '!'); if (this.binding !== val) { r.createText(this.h1, val); this.binding = val; } } //... }
  38. 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'; }
  39. --stripInternal import { Component } from 'library'; const cmp =

    new Component(); // Property 'name' does not exist on type 'Component'. cmp.name = 'Captain America';
  40. 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
  41. CD with codegen • Easier to reason about • Obviously

    fast • Inline caching performance boost • VM friendly code
  42. If the codegen happens at build time, it’s called AoT;

    if it happens at runtime, it’s called JiT
  43. 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
  44. 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 <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header>
  45. 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); //... } ... <header> <h1>Hello {{ name }}!</h1> <p> Summary of the awesome app! </p> </header> vs
  46. { "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
  47. JiT bootstrap import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import {

    AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);
  48. 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);
  49. Resources • Angular CLI • AoT in Angular 2 •

    Building an Angular 2 Application for Production • 2.5X Smaller Angular 2 Apps with GCC • Codelyzer