angular2 - in action
TRANSCRIPT
Angular 2IN ACTION
NG2 INTRODUCTION
Part 2
TSD
TSD
npm install tsd -g
tsd install angular2/angular2 angular2/router rx es6-promise
TSC
tsc app.ts --target ES5
--module system --experimentalDecorators
--moduleResolution node
--emitDecoratorMetadata
--outFile app.js
Start
HTML
<!doctype html><html lang="en">
<body><my-app></my-app><script src="js/bundle.js"></script>
</body></html>
APP.TS - IMPORTS
/// <reference path="../../typings/tsd.d.ts" />
import {Component, View, bootstrap, CORE_DIRECTIVES, FORM_DIRECTIVES, provide
} from 'angular2/angular2';
//...
APP.TS - COMPONENT
@Component({selector: 'my-app',template: APP_TEMPLATE,directives: [HeaderComponent,
ROUTER_DIRECTIVES],provides: [PostsStorage, Core]
})
class AppComponent {}
APP.TS - BOOTSTRAP
bootstrap(AppComponent, [// CommonPostsStorage,Core,
// Ng2ROUTER_PROVIDERS,HTTP_PROVIDERS,provide(APP_BASE_HREF, {useValue: '/'})
]);
Templates
TEMPLATES - IMPORT
import {
APP_TEMPLATE
} from './templates';
TEMPLATES - EXAMPLE COMPONENT
class AppComponent { text:string = 'hello';
typing($event){
this.text = $event.target.value;
}
}
TEMPLATES - CODE
<h1>Bound Textbox</h1>
<input [value]="text" (keyup)="typing($event)" />
{{text}}
TEMPLATES - SYNTAX
<todo-cmp [model]="my_value"></todo-cmp>
<input [ng-model]="todo.text"(ng-model-change)="todo.text=$event"
></input>
<input [(ng-model)]="todo.text"></input>
TEMPLATES - SYNTAX
<video-player #player></video-player>
<button (click)="player.pause()">Pause
</button>
<input #i> {{i.value}}
PIPE
PIPE - USAGE
@Pipe({name: 'publicName'
})
class ClassPipeName implements PipeTransform {
transform(value: number, args: any[]) {//…
}
}
PIPE - USAGE
@Pipe({name: 'publicName'
})
class ClassPipeName implements PipeTransform {
transform(value: number, args: any[]) {//…
}
}
Routing
ROUTING - @RouteConfig
import {AboutComponent
} from './components/about/index';
@RouteConfig([{path: '/About/:id',component: AboutComponent,name: 'About'
}])
class AppComponent {}
ROUTING - @RouteConfig
export class AboutComponent { id: number;
constructor( @Inject(RouteParams) params: RouteParams) {
this.id = params.get('id');
}}
ROUTING - TEMPLATE
<nav><ul>
<a [router-link]="['./About', {id: 1}]" href="#" class="list-group-item">About</a>
<a [router-link]="['./Home']" href="#" class="list-group-item">Home</a>
<a [router-link]="['./PostsList']" href="#" class="list-group-item">Posts list</a>
</ul></nav>
<route-transclusion name="main"></route-transclusion>
LINKS
react / angular / angular2
ng-conf
● https://github.com/htdt/ng2-jspm● https://github.com/thelgevold/angular-2-samples● http://www.syntaxsuccess.com/angular-2-articles●
BUILDING / COMPILE / TRANSCRIPTION
Part 2
Browserify
ROUTING - TEMPLATE
var browserify = require('gulp-browserify');
gulp.src('build/ts/app/app.js')
.pipe(browserify({insertGlobals : true,debug : !gulp.env.production
}))
.pipe(gulp.dest('./dist/app'))
NO
JSPM
JSMP
“jspm is a package manager for the SystemJS universal module loader, built on top of the dynamic ES6 module loader”
React applications with JSPM
JSMP
● ES6, AMD, CommonJS and globals) ● npm and GitHub...● load modules as separate files● optimize into a bundle● realtime transcript
System.js
SYSTEM.JS - PRODUCTION
npm install -g jspm
jspm init
jspm install angular2/angular2
jspm bundle-sfx --minify zone.js + whatwg-fetch + reflect-metadata + src/app/app dist/js/bundle.js
SYSTEM.JS - DEVELOPMENT
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>System.import('reflect-metadata')
.then(function(){System.import('zone.js')})
// .then(function(){System.import('es5-shim')}) <- LOL
.then(function(){System.import('es6-shim')})
.then(function(){System.import('whatwg-fetch')})
.then(function(){System.import('src/app/app')});</script>
SYSTEM.JS - PRODUCTION
<!doctype html><html lang="en">
<body><my-app></my-app><script src="js/bundle.js"></script>
</body></html>
Gulp
GULP - TEMPLATESvar ng2Template = "export const <%= template.url %> = '<%= template.escapedContent %>';\n";
function fnRename(templateUrl, templateFile) {var pathParts = templateUrl.replace('.tpl.html', '').split('/'),
folder = pathParts[pathParts.length - 2],file = pathParts[pathParts.length - 1],name = (folder ? folder + '_' : '') + file + '_TEMPLATE';return name.toUpperCase().replace(/-[\.\-]/g,
function (match) {return '_';
});}
}
/*...*/.pipe(ngHtml2Js({rename: fnRename,template: ng2Template
})
PRERENDER
Part 3
Metadata
Metadata - HTML
<!doctype html><html lang="en">
<head><title>{{ no.work.here }}</title>
<head><body>
<my-app></my-app><script src="js/bundle.js"></script>
</body></html>
METADATA - SERVICE
export class HeadDOM {private titleDom:HTMLElement;
get title():string {return this.titleDom.innerText;
}
set title(title:string) {this.titleDom.innerText = title;this.ogTitle = title;
}
//…}
Prerender.io
PRERENDER.IO - COST
PRERENDER.IO - GITHUB
https://github.com/prerender/prerender
Webrender-service
Webrender-service - Overview
● (+) Render png file● (+) Render pdf file● (+) Render html file● (+) No-overwrite js functions● (+) Servers whitelist● (+) Token security● (-) Legacy code● (-) Small community● (-) No-good tested● (-) Use node-babel● (-) Alpha
Webrender-service - Todo
● Remove babel (problems with debugging)● Write unit tests● Remove cache (I recommend to use solution like varnish)
WEBRENDER SERVICE (ALPHA) - GITHUB
https://bitbucket.org/spozoga/webrender-service
PhantomJS
PhantomJS - Error #1
Map is a pretty new structure. Use npm install harmony-collections --save-dev and add "node_modules/harmony-collections/harmony-collections.min.js", to the karma config.
PhantomJS - Error #2
ORIGINAL EXCEPTION: TypeError: 'undefined' is not a function (evaluating 'window.requestAnimationFrame(callback)')
PhantomJS - Error #3
RangeError: Maximum call stack size exceeded.
at quote (/Users/spozoga/dev/prerender/node_modules/phantom/shim.js:1065)
………..
DevOps
VARNISH
PRERENDER.IO - GITHUB
https://github.com/prerender/prerender
PRERENDER-VARNISH - GITHUB
https://github.com/MWers/prerender-varnish
The end
Sebastian Poż[email protected]