Primera setmana de codificació
La primera setmana del període de codificació de GSoC 2016 ha acabat. Vaig començar l'actualització de Jangouts d'Angular 1.x a Angular 2. Vaig completar totes les tasques dins del termini i espero mantenir aquest ritme la propera setmana.
Estic seguint la guia d'actualització de la documentació oficial d'Angular, que té dos blocs principals:
- Preparació
- Actualització amb l'Adaptador d'Actualització
Acabo d'acabar el bloc de preparació. Afortunadament, el codi de Jangouts és
clar i ja segueix dos requisits clau de preparació: la guia d'estil d'Angular i
directives de components. Això em va deixar només dues tasques: canviar
d'etiquetes <script> a un carregador de mòduls, i migrar de JavaScript a
TypeScript. Vaig invertir l'ordre, migrant a TypeScript primer i després
canviant al carregador de mòduls. Aquesta seqüència em va semblar més natural
per a aquest projecte.
Migrant a TypeScript
Jangouts té un sistema de construcció gulp funcionant, així que no vaig
necessitar preocupar-me per la càrrega de scripts. Em vaig enfocar primer en
migrar arxius a TypeScript, després vaig aprofitar la sintaxi import de
TypeScript/ES6.
Migrar codi de JavaScript a TypeScript és senzill: canvia l'extensió de .js a
.ts. El sistema gulp existent no funciona amb aquests canvis, així que executa
tsc --watch src/**/*.ts juntament amb gulp. Aquesta comanda mostra molts
errors, però si el codi JavaScript és correcte, aquests errors només es
relacionen amb la comprovació de tipus de TypeScript.
Durant aquesta migració, també vaig fer el codi més modular. Jangouts tenia tots
els components registrats en un únic mòdul Angular janusHangouts. De projectes
anteriors, vaig aprendre que això causa problemes amb proves unitàries. Ara
defineixo un mòdul separat per a cada component (janusHangouts.componentName)
i el faig dependència del mòdul principal. Això té dos avantatges: testing més
fàcil, i potencialment carregar components sota demanda amb un carregador de
mòduls.
Com vaig mencionar abans, compilar codi JavaScript amb tsc mostra molts
errors. Un error comú és:
error TS7006: Parameter '$state' implicitly has an 'any' type.
El compilador TypeScript requereix un tipus per a totes les variables. Per
permetre tipus any implícits en variables sense tipus, deshabilita
noImplicitAny a tsconfig.json.
Un altre error que podem trobar en treballar amb elements HTML és:
error TS2339: Property 'muted' does not exist on type 'HTMLElement'.
Aquest error es produeix per un codi com aquest:
var video = $("video", element)[0];video.muted = true;
TypeScript és segur en tipus: $('video', element)[0] retorna HTMLElement,
que no té la propietat muted. El subtipus HTMLVideoElement sí conté muted.
Casteja el resultat a HTMLVideoElement:
var video = <HTMLVideoElement>$('video', element)[0];video.muted = true;
Finalment, un altre error comú és:
error TS2339: Property 'id' does not exist on type '{}'.
La validació de tipus de TypeScript causa aquest error en codi com:
var room = {};// Algun codi aquí...function isRoom(room) {return room.id == roomId;}
Defineix una interfície per a l'objecte room per solucionar això i reduir errors:
interface Room {id?: number; // ? fa l'atribut opcional}// Algun codi aquí ...var room: Room = {};// Algun codi aquí...function isRoom(room: Room) {return room.id == roomId;}
Utilitzant un Carregador de Mòduls
Per què utilitzar un carregador de mòduls? El lloc d'Angular explica:
Utilitzar un carregador de mòduls com SystemJS, Webpack, o Browserify ens permet utilitzar els sistemes de mòduls integrats dels llenguatges TypeScript o ES2015 en les nostres aplicacions. Podem utilitzar les característiques d'import i export que explícitament especifiquen quin codi pot i serà compartit entre diferents parts de la aplicació. [...]
Quan després portem les nostres aplicacions a producció, els carregadors de mòduls també fan més fàcil empaquetar-les totes en paquets de producció amb bateries incloses.
Vaig descartar Browserify per males experiències passades i només vaig provar SystemJS i Webpack.
SystemJS
SystemJS sembla net i simple. Defineix un punt d'entrada (típicament l'arxiu
principal de l'aplicació) i la sintaxi import fa la resta. Amb declaracions
import correctes, tot funciona.
Tanmateix, aquesta solució requereix conservar gulp ja que SystemJS només maneja importacions. Això significa afegir el compilador TypeScript a gulp i deshabilitar l'auto injecció de scripts en HTML.
Abans de reescriure la configuració de gulp, volia provar Webpack primer.
Webpack
La configuració de Webpack és més complexa que SystemJS, però reemplaça gulp
completament. Com SystemJS, definim un punt d'entrada i especifiquem on és
index.html per a la inclusió d'arxius JavaScript.
Vaig tenir problemes inicials, però després d'estudiar exemples, vaig aconseguir
una versió funcional. Explorant Webpack més a fons, vaig trobar el que em va fer
triar-lo: podem fer import o require d'arxius no JavaScript. Podem requerir
la plantilla d'una directiva Angular, i el procés de construcció la inclou com a
variable string dins del component. Els estils funcionen igual. Això millora el
rendiment empaquetant tots els arxius que un component necessita en el seu arxiu
JavaScript, sense complicar el desenvolupament.
Una cosa més
Aquest estiu sembla emocionant amb tot el que aprendré a través de GSoC. Segueix el meu progrés en aquest blog o a través de les meves contribucions a GitHub. També vaig publicar un tauler de Trello amb la planificació i tasques del projecte (encara actualitzant-se).