TORNAR

Primera setmana de codificació

5 min de lectura

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).