Vista de pájaro al código de una aplicación Angular (4)

  • Por
Una aproximación a los elementos principales que encontramos en una aplicación Angular, versión 4, entendiendo el código.

En el capítulo anterior ofrecimos una descripción general de la estructura de carpetas de una aplicación Angular, junto con algunos de sus principales archivos. Ahora vamos a introducirnos en el código y tratar de entender cómo está construida, al menos cuál es el flujo de ejecución de los archivos que vamos a encontrar.

La aplicación que vamos a radiografiar es la que conseguimos mediante el comando "ng new" del CLI. Esperamos que ya tengas tu aplicación generada. Si no es así, te recomendamos antes la lectura del artículo de Angular CLI. Vamos a usar la versión 4 de Angular, aunque serviría para cualquier versión del framework a partir de la 2.

Obviamente no podremos cubrir todos los detalles, pero esperamos que de este artículo te ofrezca bastante luz sobre cómo se ejecutan los archivos principales de Angular. Verás que iremos saltando de un archivo a otro, dentro de la aplicación básica generada con "ng new", recorriendo básicamente el flujo de ejecución. Al final tendrás un resumen completo de los pasos de este recorrido que esperamos te sirva para apreciarlo de manera general.

Nota: lo cierto es que este artículo cubre Angular desde que se pasó a Webpack. En las versiones tempranas de Angular 2, usaban SystemJS para la gestión y carga de dependencias. El código de una aplicación usando esa versión antigua ya se explicó en el artículo Zambullida en el código del proyecto inicial de Angular 2.

Archivo Index.html

Es de sobra sabido que las aplicaciones web comienzan por un archivo llamado index.html. Con Angular además, dado que se construyen páginas SPA (Single Page Application) es todavía más importante el index.html, pues en principio es el archivo que sirve para mostrar cualquier ruta de la aplicación.

El index.html en nuestra aplicación Angular, como cualquier otro archivo de los que forman parte de la app, se encuentra en el directorio "src". Si lo abres podrá llamarte la atención al menos un par de cosas:

Ausencia de Javascript:

No hay ningún Javascript de ningún tipo incluido en el código. En realidad el código Javascript que se va a ejecutar para inicializar la aplicación es inyectado por Webpack y colocado en el index.html cuando la aplicación se ejecuta o cuando se lleva a producción.

El BODY prácticamente vacío:

En el cuerpo de la página no aparece ningún HTML, salvo una etiqueta "app-root". Esta es una etiqueta no estándar, que no existe en el HTML. En realidad es un componente que mantiene todo el código de la aplicación.

Nota: Deberíamos hacer un stop al análisis del código para nombrar la "Arquitectura de componentes". En Angular y en la mayoría de librerías y frameworks actuales se ha optado por crear las aplicaciones en base a componentes. Existe un componente global, que es la aplicación entera y a su vez éste se basa en otros componentes para implementar cada una de sus partes. Cada componente tiene una representación y una funcionalidad. En resumen, las aplicaciones se construyen mediante un árbol de componentes, que se apoyan unos en otros para resolver las necesidades. En el index.html encontramos lo que sería el componente raíz de este árbol. Comenzamos a ver más detalle sobre los componentes en el siguiente artículo Introducción a los componentes en Angular 2.

Archivo main.ts

Como hemos visto, no existe un Javascript definido o incluido en el index.html, pero sí se agregará más adelante para que la aplicación funcione. De hecho, si pones la aplicación en marcha con "ng serve -o" se abrirá en tu navegador y, al ver el código fuente ejecutado podrás ver que sí hay código Javascript, colocado antes de cerrar el BODY del index.html.

Ese código está generado por Webpack, e inyectado al index.html una vez la página se entrega al navegador. El script Javascript que el navegador ejecutará para poner en marcha la aplicación comienza por el archivo main.ts, que está en la carpeta "src".

Nota: Podría llamarte la atención que no es un archivo Javascript el que contiene el código de la aplicación, pero ya dijimos en la Introducción a Angular, que este framework está escrito usando el lenguaje TypeScript. En algún momento ese código se traducirá, lógicamente, para que se convierta en Javascript entendible por todos los navegadores. Ese proceso lo realiza Webpack pero realmente no debe preocuparnos mucho ya que es el propio Angular CLI que va a realizar todas las tareas vinculadas con Webpack y el compilador de Javascript para la traducción del código, de manera transparente para el desarrollador.

Si abres el main.ts observarás que comienza realizando una serie de "import", para cargar distintas piezas de código. Esos import son típicos de ES6, aunque en este caso te los ofrece el propio TypeScript, ya que el transpilador de este lenguaje es el que los convertirá a un Javascript entendible por todos los navegadores.

Los import que encuentras los hay de dos tipos.

1.- imports de dependencias a librerías externas

Estos import son código de otros proyectos, dependencias de nuestra aplicación. Están gestionados por npm y han sido declarados como dependencias en el archivo package.json que deberías conocer. Tienen la forma:

import { enableProdMode } from '@angular/core';

En este caso nos fijamos en '@angular/core' que es una de las librerías dependientes de nuestra aplicación, instaladas vía npm, cuyo código está en la carpeta "node_modules". En esa carpeta, de código de terceros, nunca vamos a tocar nada.

2.- Imports a código de nuestro propio proyecto

También encontraremos imports a elementos que forman parte del propio código de la aplicación y que por tanto sí podríamos tocar. Los distingues porque tienen esta forma:

import { AppModule } from './app/app.module';

Aquí nos fijamos en la ruta del módulo que se está importando './app/app.module', que es relativa al propio main.ts.

Nota: en la ruta al archivo que se está importando falta el ".ts", ya que el archivo es un TypeScript. Pero realmente no se debe colocar, puesto que ese archivo .ts en algún momento se traducirá por un archivo .js. Para no liarse, recuerda que los import a archivos TypeScript no se coloca la extensión.

Obviamente, para profundizar habría que entender qué es cada import de los que se van realizando, los cuales tendremos tiempo de analizar llegado el momento.

Además de los imports, que es código que se va requiriendo, hay un detalle que encontramos al final del fichero:

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));

Esto es el bootstrap, el arranque, de la aplicación, que permite decirle a Angular qué tiene que hacer para comenzar a dar vida a la aplicación. Al invocar al sistema de arranque estamos indicando qué módulo (AppModule) es el principal de la aplicación y el que tiene los componentes necesarios para arrancar.

Al final, el bootstrap provocará que Angular lea el código del módulo y sepa qué componentes existen en el index, para ponerlos en marcha, provocando que la aplicación empiece a funcionar, tal como se haya programado.

Nota: fíjate que para arrancar la aplicación se hace uso de los elementos que hemos importado en las líneas anteriores, entre ellos platformBrowserDynamic y AppModule.

Archivo app.module.ts

De entre todos los imports que se hace en el main.ts hay uno fundamental, que nos sirve para tirar del hilo y ver qué es lo que está pasando por abajo, para hacer posible que todo comience a funcionar. Se trata de app.module.ts, que podemos considerar como el módulo principal de la aplicación.

En este fichero nos encontramos, como viene ya siendo habitual, varios imports de elementos que vienen de otros módulos, pero hay además dos cosas que pueden ser clave para entender el flujo de ejecución.

Import de nuestro componente raíz

En el módulo principal, app.module.ts, encontramos el import al componente raíz de la aplicación (esa etiqueta HTML no-estándar que aparecía en el BODY del index).

import { AppComponent } from './app.component';

Este componente es importante en este punto porque es el primero que estamos usando y porque es el único que te ofrecen ya construido en la aplicación básica creada con el CLI de Angular.

Al importar el componente lo que estamos obteniendo es una referencia "AppComponent", donde estará la clase creada para implementar el componente.

Decorador @NgModule

Esta es la primera vez que quizás estás conociendo los decoradores, algo que viene directamente otorgado por TypeScript. Los decoradores permiten asignar metadata a funciones, clases u otras cosas. Las funciones decoradoras tienen un nombre y las usamos para asignar esos datos, que podrían modificar el comportamiento de aquello que se está decorando.

El decorador completo en la versión de Angular que estamos usando (4) es este:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

Como ves, a la función decoradora la alimentamos con un objeto pasado por parámetro, en el que indicamos diversos datos útiles para la clase AppModule. Este decorador se irá editando y agregando nuevas cosas a medida que vayamos desarrollando, por lo que nos resultará bastante familiar a poco que comencemos a desarrollar con Angular.

En el decorador hay una propiedad llamada "bootstrap", que contiene un array con los componentes que Angular tiene que dar vida, para conseguir que las cosas comiencen a funcionar: bootstrap: [AppComponent]. Esto le dice a Angular que hay en el index.html hay un componente implementado con la clase AppComponent, que tiene que ejecutar.

Componente raíz de la aplicación

Para llegar al meollo del código, tenemos que observar, aunque todavía por encima, el componente raíz. Lo habíamos usado en el index.html:

<app-root></app-root>

Pero echemos un vistazo al código del componente. Su ruta la puedes deducir del import que se ha realizado en el app.module.ts, o sea "src/app/app.component.ts".

De momento solo queremos que encuentres tu segundo decorador, con el código siguiente.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
  • El selector o etiqueta que implementa este componente: "app-root". Justamente es la etiqueta extraña que había en el index.html.
  • El archivo .html su template: "./app.component.html".
  • Los estilos CSS que se usan en el componente: "./app.component.css"

Con lo que acabas de ver, será fácil abrir encontrar el archivo donde está el template. ¿no? Puedes abrirlo y verás el código HTML que aparecía al poner en marcha la aplicación. (Comando "ng serve -o" del CLI)

Resumen del flujo de ejecución de la aplicación básica Angular (4)

Somos conscientes que hemos aportado muchos datos en este artículo, quizás demasiados para asimilarlos en una primera lectura. Si todo es nuevo para ti debe de ser un poco complicado hacerse un esquema perfecto del funcionamiento de las cosas, así que vamos a parar un momento para repasar de nuevo el flujo de ejecución del código.

  1. En el index.html tenemos un componente raíz de la aplicación "app-root".
  2. Al servir la aplicación (ng serve), o al llevarla a producción (ng build) la herramienta Webpack genera los paquetes (bundles) de código del proyecto y coloca los correspondientes scripts en el index.html, para que todo funcione.
  3. El archivo por el que Webpack comienza a producir los bundles es el main.ts
  4. Dentro del main.ts encontramos un import del módulo principal (AppModule) y la llamada al sistema de arranque (bootstrapModule) en la que pasamos por parámetro el módulo principal de la aplicación.
  5. En el módulo principal se importa el componente raíz (AppComponent) y en el decorador @NgModule se indica que este componente forma parte del bootstrap.
  6. El código del componente raíz tiene el selector "app-root", que es la etiqueta que aparecía en el index.html.
  7. El template del componente raíz, contiene el HTML que se visualiza al poner en marcha la aplicación en el navegador.

Conclusión

Por fin hemos llegado a seguir la ejecución de la aplicación, para encontrar su contenido. Seguro que habiendo llegado a este punto sentirás una pequeña satisfacción. Puedes aprender más de los componentes en el artículo Introducción a los componentes en Angular 2.

Somos conscientes que mucho del conocimiento ha quedado en el aire y hay muchas dudas que querrás resolver, pero con lo que hemos visto hemos conseguido el objetivo planteado, disponer de una vista de pájaro del código que encuentras al iniciar tu aplicación Angular.

Puedes continuar la lectura del Manual de Angular para obtener más información sobre decoradores, componentes, y arranque de las aplicaciones.