Twitter: Andres Gesteira (@GeorgeKaplan_G)
Angular 2 Developer
Antes Wordpres & Drupal Developer
Ahora trabajando para GFT
(@kaplan81)
E-mail: gesteira2046@gmail.com
Angular 2
Reescritura completa de Ng1 en Typescript.
Basado en componentes controlados por el framework.
Multiplataforma
Altísimo rendimiento.
Angular CLI
Lo peor de Javascript:
The worst of all of JavaScript's bad features is its dependence on global variables. A global variable is a variable that is visible in every scope. Global variables can be a convenience in very small programs, but they quickly become unwieldy as programs get larger.
las variables globales
Douglas Crockford
Javascript: The Good Parts
JS: problemática de los módulos
ECMAScript2015 incorpora el patrón modular...
...pero los navegadores no, porque no tienen un objeto System.
Otro mejor: escribir módulos y luego transpilar.
Un rodeo: Immediately-Invoked Function Expressions (IIFE).
Las variables globales son contrarias al patrón modular.
Tipos de módulos (I):
Asynchronous Module Definition (AMD)
Es el de RequireJS, y tiene este aspecto:
// file for exporting (jquery.js)
define(['jquery'] , function ($) {
return function () {};
});
// file for importing (app.js)
var $ = require('jquery');
Tipos de módulos (II):
CommonJS
Es el de Node y tiene este aspecto:
// file for exporting (jquery.js)
var jquery = function ($) {
return function () {};
};
module.exports = jquery;
// file for importing (app.js)
var $ = require('jquery.js');
Tipos de módulos (III):
ES Harmony
Es el de ECMAScript, y tiene este aspecto:
// file for exporting (jquery.js)
export function jquery($) {
return function() {};
}
// file for importing (app.js)
import { jquery } from 'jquery';
Cómo va a estar estructurada
index.html con un componente padre <app-root></app-root>
main.ts con un método de bootstraping.
Carpeta 'app' con módulos que contienen componentes.
main.ts
Lanza la aplicación cargando el módulo principal.
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/';
platformBrowserDynamic().bootstrapModule(AppModule);
El método proviene de una librería multiplataforma.
app.module.ts
Importa los otros módulos de mi aplicación.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HomeModule } from './home/home.module';
import { NotFoundModule } from './not-found/not-found.module';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { UserService } from './user.service';
@NgModule({
imports: [
BrowserModule,
HomeModule,
NotFoundModule,
AppRoutingModule
],
declarations: [AppComponent],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
Declara y lanza el componente padre.
Declara los servicios de mi aplicación.
app.component.ts
Es la declaración de nuestro componente padre.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }
Lleva asociado un template de HTML y, ocasionalmente, una hoja de estilos de CSS.
¿Qué necesita nuestro navegador?
No sabe Typescript. Tendremos compilar a Javascript.
No entiende Angular. Habrá que aplicar un Abstract Syntax Tree (AST).
No conoce los módulos. Habrá que utilizar un module loader que gestiones el Dependency Graph.
Le cuesta gestionar muchos archivos, así que estaría bien que optimizáramos el resultado final creando bundles.
Webpack te lo hace TODO
¿Por qué Webpack y no SystemJS?
Con SystemJS tendríamos que acabar añadiendo un gestor de tareas como Grunt o Gulp.
Webpack crea bundles de archivos, pero también es capaz de seguir el gráfico de dependencias de los módulos.
Los loaders de Webpack tienen las mismas capacidades que Grunt o Gulp.
Funciona tanto en el lado del cliente como en el lado del servidor.
Ha sido incorporado a la Angular CLI.
Tiene algo único: el Hot Module Replacement.
Dispone de todo tipo de plugins de optimización.
¿Por qué Webpack 2 y no Webpack 1?
Sintaxis de configuración algo más clara.
Soporta import/export de ES Harmony Modules.
Soporta System.import de SystemJS.
¿Qué es?
La expresión proviene de la Navidad norteamericana.
Consiste en eliminar los todos aquellos elementos que han sido exportados pero no importados.
Se produce cuando uglificamos archivos compilados a ES2015.
¿Y qué es eso de uglificar?
Es un proceso de parseo de nuestro código (ugligy) que nos lo pone "más feo". Suele constar de dos pasos:
1) Minificación: quita los espacios en blanco y los comentarios.
2) Compresión: lo pone todo en una línea.
tsconfig.json
Debe especificar un módulo resultante tipo "es2015".
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"inlineSourceMap": true,
"sourceMap": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"./node_modules/@types/"
]
}
}
my-es2015-output.js
Después de la compilación:
function(module, exports, __webpack_require__) {
/* harmony export */ exports["foo"] = foo;
/* unused harmony export bar */;
function foo() {
return 'foo';
}
function bar() {
return 'bar';
}
}
my-es2015-output.min.js
Después de la minificación:
function (t, n, r) {
function e() {
return "foo"
}
n.foo = e
}
¿Qué es?
Consiste en no cargar todos los módulos a la vez.
Al entrar en nuestra aplicación se cargarán sólo los módulos que se renderizan en la Home.
El resto se irá cargando de manera "perezosa" a medida que los vayamos necesitando.
En Angular 2 esta funcionalidad nos la ofrece el Router.
Puede causar conflicto con la compilación AOT.
app-routing.module.ts
import { NgModule, ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { NotFound } from './not-found/not-found.component';
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{
path: 'dashboard',
loadChildren: './+dashboard/dashboard.module#DashboardModule'
},
{
path: 'wikipedia',
loadChildren: './+wikipedia/wikipedia.module#WikipediaModule'
},
{ path: '**', component: NotFound }
];
const routing: ModuleWithProviders = RouterModule.forRoot(
routes,
{ useHash: true }
);
@NgModule({
imports: [routing],
exports: [RouterModule]
})
export class AppRoutingModule {}
¿Qué son?
El compilador de Angular 2 por defecto hace uso del Typescript Compiler (tsc) y produce una compilación Just-In-Time (JIT).
El compilador de la Angular CLI (ngc) realiza su propia compilación de Typescript y posee la virtud de elegir entre JIT y Ahead-Of-Time (AOT).
En el modo JIT la aplicación se compila en el navegador, en tiempo de ejecución.
En el modo AOT se le ofrece al navegador una aplicación precompilada.
Ventajas de la AOT
La aplicación está precompilada, así que la renderización de la pagina es mucho más rápida.
No existe la necesidad de incluir el compilardor por defecto dentro de nuestra aplicación, así que el peso del archivo a descargar en el navegador es mucho menor.
Se detectan errorres de manera más temprana.
Es más segura.
JIT compilation
Inputs
(TS)
AST
Parse & Generate
SERVER
BROWSER
JS
eval()
JS
factories
new...
Running
App
tsc
AOT compilation
Inputs
(TS)
AST
Parse & Generate
SERVER
BROWSER
JS
<script>
**TS
factories
new...
Running
App
*ngc
**Muy diferentes de las JS factories en JIT.
*ngc + tsc en nuestra aplicación.
tsconfig-aot.json
Gestiona nuestra precompliación AOT.
{
"compilerOptions": {
// SAME AS BEFORE
},
// PLUS OTHER OPTIONS
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit": true
}
}
Se ejecuta con el comando:
node_modules/.bin/ngc -p tsconfig-aot.json
main-aot.ts
Lanza la aplicación cargando la factoría precompilada.
import { platformBrowser } from '@angular/platform-browser';
import { enableProdMode } from '@angular/core';
import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory';
enableProdMode();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);