Movent grans parts a Angular 2
En un post anterior vaig explicar com vaig convertir Jangouts en una aplicació híbrida Angular 1+2. Aquest enfocament, en lloc d'una migració completa, té dos objectius. Primer, provar la funcionalitat resulta més fàcil ja que Jangouts segueix sent executable. Segon, si no puc acabar la migració, altres poden continuar la feina. Espero que aquest pla alternatiu resulti innecessari.
Amb l'enfocament híbrid implementat, aquesta setmana vaig migrar diversos components a Angular 2. Vaig començar amb el component Chat---més complex que el Footer, però manejable per a aquestes etapes inicials.
Migrant subcomponents
El component Chat de Jangouts té tres subcomponents a més del component principal:
chat-message: Renderitza els missatges de l'usuari.log-entry: Renderitza les notificacions del sistema (com "L'usuari X s'ha unit").chat-form: Gestiona l'entrada de missatges.
Aquests subcomponents són simples: cadascun té una classe de component mínima i
una plantilla. El canvi clau: els estils van passar de l'arxiu scss principal
a arxius independents per a cada subcomponent. Això aprofita
Angular 2 View Encapsulation,
assegurant que els estils s'apliquin només al seu component.
Durant la migració de chat-message, vaig trobar un problema amb
ngEmbed, la llibreria que proporciona una
directiva per renderitzar missatges d'usuari. Aquesta directiva habilita emojis
i enllaços, imatges i vídeos incrustats. La llibreria no té suport per a Angular
2, així que vaig provar
l'Angular 2 Upgrade Adapter,
però vaig trobar un error estrany.
La investigació va revelar que ngEmbed utilitza una funció com a atribut
templateUrl (permès en Angular 1). Tanmateix, l'adaptador d'actualització de
la meva versió actual d'Angular 2 no suporta templateUrl basat en funcions. La
branca master d'Angular 2 inclou aquest suport, però cap versió publicada
l'incorpora encara. Després de discutir amb els meus mentors, vam decidir
deshabilitar aquesta funcionalitat i continuar la migració.
Espero re-habilitar-lo en el futur.
Diferenciar entre component i directiva
Migrar el component principal va resultar més complex. Mostra tots els missatges (d'usuari i sistema) en una vista que fa auto-scroll quan arriben nous missatges. A l'antic Jangouts, una directiva renderitzava la llista de missatges i controlava l'auto-scroll. Angular 2 requereix un enfocament diferent: els components sempre tenen plantilles i mai interactuen directament amb el DOM; les directives mai tenen plantilles però poden interactuar amb el DOM.
Això va significar dividir el component principal del xat en dues parts:
- Un component per renderitzar la llista de missatges.
- Una directiva per gestionar l'auto-scroll.
Després de la migració, el component renderitza la llista de missatges i conté la directiva que gestiona l'auto-scroll.
Posant tot junt
Durant la migració de subcomponents, vaig degradar cadascun per a compatibilitat amb Angular 1 utilitzant l'adaptador d'Angular 2 i vaig provar manualment amb l'antic component principal. Quan vaig migrar el component principal, el seu codi es va convertir en Angular 2 pur (sense subcomponents degradats). Només el component principal del xat va necessitar degradació per a compatibilitat amb Angular 1.
Aplicant l'estructura d'aplicació correcta
Els canvis d'aquesta setmana van anar més enllà del codi. També vaig reestructurar l'aplicació seguint les recomanacions de la guia d'estil. Abans de la migració, l'estructura era:
src└── app├── adapter.ts├── variables.scss├── index.scss├── vendor.scss├── index.ts├── components│ ├── chat│ │ ├── chat-form.directive.html│ │ ├── chat-form.directive.js│ │ ├── chat.directive.html│ │ ├── chat.directive.js│ │ ├── chat-message.directive.html│ │ ├── chat-message.directive.js│ │ ├── log-entry.directive.html│ │ └── log-entry.directive.html│ ├── footer│ │ ├── footer.directive.html│ │ └── footer.directive.js│ └── [...]└── [...]
Després dels canvis:
src└── app├── adapter.ts├── variables.scss├── index.scss├── vendor.scss├── index.ts├── chat│ ├── index.ts│ ├── chat.component.html│ ├── chat.component.scss│ ├── chat.component.spec.ts│ ├── chat.component.ts│ ├── chat-form│ │ ├── chat-form.component.html│ │ ├── chat-form.component.spec.ts│ │ ├── chat-form.component.ts│ │ └── index.ts│ ├── chat-message│ │ ├── chat-message.component.html│ │ ├── chat-message.component.scss│ │ ├── chat-message.component.spec.ts│ │ ├── chat-message.component.ts│ │ └── index.ts│ ├── log-entry│ │ ├── index.ts│ │ ├── log-entry.component.html│ │ ├── log-entry.component.spec.ts│ │ └── log-entry.component.ts│ └── message-autoscroll.directive.ts├── footer│ ├── footer.component.html│ ├── footer.component.scss│ ├── footer.component.spec.ts│ ├── footer.component.ts│ └── index.ts├── components│ └── [...] // Això conté el codi no migrat└── [...]
Treballant actualment
Ara estic migrant el component Feed, un dels més complexos a l'aplicació degut als seus molts serveis que gestionen streams de vídeo/àudio.
He mogut tots els serveis i factories a Angular 2, però encara no he habilitat la compatibilitat amb Angular 1. La raó: vull una suite de tests completa cobrint aquests serveis abans de continuar la migració i integrar amb la resta de l'aplicació.