Angular 2

The Shiny Parts

Maxim Salnikov

@webmaxru

  • Google Developer Expert in Angular

  • AngularJS Oslo Meetup organizer

  • Mobileera.Rocks conf organizer

Products from the future

UI Engineer at ForgeRock

Google Developer Experts

Google Experts are a global network of experienced product strategists, designers, developers and marketing professionals actively supporting developers, startups and companies changing the world through web and mobile applications.

The Pale Parts

2 years of development

Not backwards compatible

Bre

a

king

ch

ange

s

Flexibility

ES

ES2015

ES2016

TS

Versatility

Performance

Performance

Ahead of Time compilation

Change detection

Server-side rendering

Web Workers

Compiler

A compiler is a computer program that transforms source code written in a programming language into another computer language [...] The most common reason for converting source code is to create an executable program.

JIT

Just-in-time (JIT) compilation, also known as dynamic translation, is compilation done during execution of a program – at run time...

Application

Compiler

AOT

Ahead-of-time (AOT) compilation is the act of compiling a high-level programming language, into a native machine code with the intention of executing the resulting binary file natively. AOT produces machine optimized code...

Application

Compiler

Machine optimized?

createInternal(rootSelector:string):import4.AppElement {
    const parentRenderNode:any = this.renderer.createViewRoot(this.declarationAppElement.nativeElement);
    this._el_0 = this.renderer.createElement(parentRenderNode,'md-toolbar',this.debug(0,0,0));
    this.renderer.setElementAttribute(this._el_0,'class','extend-toolbar');
    this._appEl_0 = new import4.AppElement(0,(null as any),this,this._el_0);
    var compView_0:any = import14.viewFactory_MdToolbar0(this.viewUtils,this.injector(0),this._appEl_0);
    this._MdToolbar_0_4 = new import12.MdToolbar(new import15.ElementRef(this._el_0),this.renderer);
    this._appEl_0.initComponent(this._MdToolbar_0_4,[],compView_0);
    this._text_1 = this.renderer.createText((null as any),'\n  ',this.debug(1,0,35));
    this._el_2 = this.renderer.createElement((null as any),'span',this.debug(2,1,2));
    this._text_3 = this.renderer.createText(this._el_2,'\n    ',this.debug(3,1,8));
    this._el_4 = this.renderer.createElement(this._el_2,'a',this.debug(4,2,4));
    this.renderer.setElementAttribute(this._el_4,'href','#/home');
    this._text_5 = this.renderer.createText(this._el_4,'\n      ',this.debug(5,2,21));
    this._el_6 = this.renderer.createElement(this._el_4,'img',this.debug(6,3,6));
    this.renderer.setElementAttribute(this._el_6,'alt','Sfeir');
    this.renderer.setElementAttribute(this._el_6,'aria-label','foobar');
    this.renderer.setElementAttribute(this._el_6,'src','assets/images/logo-foo.svg');
    this._text_7 = this.renderer.createText(this._el_4,'\n    ',this.debug(7,3,77));
    this._text_8 = this.renderer.createText(this._el_2,'\n  ',this.debug(8,4,8));
    this._text_9 = this.renderer.createText((null as any),'\n\n  ',this.debug(9,5,9));
    this._el_10 = this.renderer.createElement((null as any),'span',this.debug(10,7,2));
    this.renderer.setElementAttribute(this._el_10,'class','flex');
    this._text_11 = this.renderer.createText((null as any),'\n\n  ',this.debug(11,7,28));
    this._el_12 = this.renderer.createElement((null as any),'span',this.debug(12,9,2));
    this._text_13 = this.renderer.createText(this._el_12,'\n    ',this.debug(13,9,8));
    this._el_14 = this.renderer.createElement(this._el_12,'a',this.debug(14,10,4));
    this.renderer.setElementAttribute(this._el_14,'href','#/locator');
    this._text_15 = this.renderer.createText(this._el_14,'Maps',this.debug(15,10,24));
    this._text_16 = this.renderer.createText(this._el_12,'\n    ',this.debug(16,10,32));
    this._el_17 = this.renderer.createElement(this._el_12,'a',this.debug(17,11,4));
    this.renderer.setElementAttribute(this._el_17,'href','#/app');
    this._text_18 = this.renderer.createText(this._el_17,'List',this.debug(18,11,23));
    this._text_19 = this.renderer.createText(this._el_12,'\n  ',this.debug(19,11,31));
    this._text_20 = this.renderer.createText((null as any),'\n',this.debug(20,12,9));

Benefits?

Application

Smaller bundle size

Fewer async requests

Faster rendering

Benefits?

Tree Shaking!

A technique to "shake" off unused code, thus shrinking the size of the deployed application

Drawbacks?

Needs compilation context

@NgModule

@NgModule({
  imports: [
    BrowserModule, MdModule,
    HttpModule, RoutesModule...
  ],
  declarations: [
    HomeComponent, ShinyComponent...
  ],
  providers: [ ShinyService ],
  bootstrap: [ AppComponent ]
})

Unified codebase

// The browser platform with a compiler
import { 
   platformBrowserDynamic 
} from '@angular/platform-browser-dynamic';


// The app module
import { AppModule } from './app.module';


// Compile (JIT) and launch the module
platformBrowserDynamic().bootstrapModule(
   AppModule
);
// The browser platform with a compiler
import { 
   platformBrowser 
} from '@angular/platform-browser';

// The generated app factory (AOT)
import { 
   AppModuleNgFactory
} from './app.module.ngfactory';

// Launch with the app module factory.
platformBrowser().bootstrapModuleFactory(
   AppModuleNgFactory
);

Dev

Prod

Some tools needed...

$ npm install \
        @angular/compiler-cli \
        @angular/platform-server \
        @angular/compiler \
        typescript@next --save

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

$ # generates app.module.ngfactory.ts
$ # generates app.component.ngfactory.ts
$ # generates app.component.css.shim.ts
$ # generates ...

Change detection

The change detection graph is a directed tree. As a result: 3-10x faster than Angular 1.x

An Angular 2 app is a reactive system

The change detection system propagates bindings from the root to leaves

Strategies

changeDetection: ChangeDetectionStrategy.Default

Strategies

changeDetection: ChangeDetectionStrategy.Default

Strategies

changeDetection: ChangeDetectionStrategy.OnPush

Strategies

changeDetection: ChangeDetectionStrategy.OnPush

Under the hood

Scalability

Scalability

Lazy-loading

Scalable communication layer

Reusability

Unfortunately the ''C'' in CSS is ''cascade"

Ideally the ''C'' in CSS would be ''component"

Shadow DOM fixes CSS and DOM. It introduces scoped styles to the web platform.

ViewEncapsulation.Native
ViewEncapsulation.Emulated
<!-- Original DOM -->
<hero-details>
    <h2>Mister Fantastic</h2>
    <hero-team>
        <h3>Team</h3>

    </hero-team>

</hero-detail>

<!-- Original CSS -->
hero-details {

    display: block;

    border: 1px solid black;

}

h3 {
    background-color: white;

    border: 1px solid #777;

}
<!-- Rendered DOM -->
<hero-details _nghost-pmm-5>

    <h2 _ngcontent-pmm-5>Mister Fantastic</h2>

        <hero-team _ngcontent-pmm-5 _nghost-pmm-6>

            <h3 _ngcontent-pmm-6>Team</h3>

        </hero-team>

</hero-detail>

<!-- Rendered CSS -->
[_nghost-pmm-5] {

    display: block;

    border: 1px solid black;

}

h3[_ngcontent-pmm-6] {

    background-color: white;

    border: 1px solid #777;

}

Convenience

CLI

npm install -g angular-cli
ng new my-shiny-app
cd my-shiny-app
ng serve
ng generate component my-shiny-component
ng g component my-shiny-component
ng g class my-shiny-class
ng g service my-shiny-service
ng build --dev
ng build --prod

ng test
ng e2e
ng github-pages:deploy --message "Go!"

On the way back

Generating routes

Support for offline applications

Mobile Toolkit

Service Workers

App Shell

Manifest generation

Workflow built into CLI

Þakka þér!

@webmaxru

Maxim Salnikov

Angular 2. The Shiny Parts.

By Maxim Salnikov

Angular 2. The Shiny Parts.

1. Intro aka what is “shiny” and why it makes us awesome 2. AOT Compilation - improve performance 3. Change Detection - sane data flow 4. View Encapsulation - build portable components 5. Hierarchical Dependency Injection - improve composability 6. Observables - reduce complexity 7. Angular CLI - convenience 8. Outro aka now go be awesome

  • 2,660