Dejad de Utilizar el Shared Material Module
Algunas cosas no merece la pena compartirlas
Este artículo describe un experimento que demuestra que utilizar un módulo Material compartido es una mala idea, ya que provoca el aumento del tamaño del bundle.
En este artículo, voy a hablar sobre un error que he cometido, y que he visto cometer a muchos desarrolladores, que es el utilizar un módulo Material compartido. Puedo asegurar que si habéis utilizado Angular Material, tendréis un módulo Material compartido en vuestro código. Es hora de eliminarlo.
Cuál es mi motivación
Actualmente estoy trabajando en un nuevo proyecto que contiene una gran cantidad de módulos y más de 20k líneas de código; y estuve trabajando en hacer que algunos de los módulos se cargasen de forma lazy/perezosa. Entonces, me di cuenta de que utilizábamos el Material Module en todos los módulos. Al principio, pensé que daba igual, pero después llevé a cabo el experimento que demuestra que es una mala idea hacerlo así.
Hora de demostrar que nos equivocamos
En mi último proyecto teníamos componentes personalizados como Grid, Tablas, Forms y acabé utilizando un Material Module compartido considerablemente grande, además de que todos los componentes estuviesen construidos sobre el Angular Material Component. Ahora, es el momento de demostrarme a mí mismo que no fue un buen enfoque.
Vamos a crear una App nueva, y vamos a ver cuáles son los problemas con este enfoque y como provoca un incremento en el tamaño del bundle. Utilizaremos webpack-bundle-analyzer
para comprobar el tamaño del bundle. Para crear una aplicación nueva, después de asegurarnos de tener la última versión del CLI, ejecutamos el siguiente comando:
ng new demoapp
Después, instalamos webpack-bundle-analyzer
mediante el siguiente comando:
npm install --save-dev webpack-bundle-analyzer
Y añadimos el siguiente script en nuestro package.json
:
"analyze": "ng build --prod --stats-json && webpack-bundle-analyzer ./dist/demoapp/stats-es2015.json"
Para ver el análisis, ejecutamos el siguiente comando:
npm run analyze
Como podemos observar en la imagen, el anterior comando abre una página que nos muestra el análisis.
Ahora, añadiremos Angular Material con el siguiente comando:
ng add @angular/material
Si ejecutamos el comando npm run analyze
otra vez y nos fijamos en el tamaño del bundle principal, podemos ver que ha aumentado en 70KB a pesar de no haber utilizado ni un solo componente de Angular Material.
Ahora, vamos a añadir dos módulos: employee y department, mediante el siguiente comando, teniendo en cuenta que no les añadiremos carga lazy en este primer ejemplo:
ng g m employee --routing --module app
ng g c employee --export true
ng g m department --routing --module app
ng g c department --export true
Abrimos el app.component.html
y reemplazamos el template por defecto con este código:
<app-employee></app-employee>
<app-department></app-department>
Si volvemos a analizar el tamaño del bundle en este momento en el que apenas tenemos código, habrá habido un ligero cambio en el tamaño, que ahora es menor. Esto es debido a que el template por defecto contiene una gran cantidad de markups y de CSS.
Ahora vamos a añadir código en ambos componentes, para ello, copiaremos código de la documentación de Material. Tenemos que añadir el siguiente código a los componentes department y employee respectivamente:
Solo nos queda hacer un único cambio en el department.component.ts
, añadiendo la siguiente propiedad:
panelOpenState = false;
Ahora sería el momento de añadir algún módulo Material a nuestros módulos employee y department, para evitar los errorores al hacer el build. La mayoría decidiríamos crear un módulo Material compartido:
ng g m shared/material --flat true
Y añadiríamos el siguiente código al módulo recién creado:
Ahora, incluimos nuestro módulo Material recién creado en los módulos employee y department:
imports: [
CommonModule,
MaterialModule
]
Si volvemos a ejecutar script del analizador, podremos ver un aumento de 216 KB en el tamaño del bundle:
Para optimizar la aplicación, lo siguiente que haremos es implementar la carga perezosa en los módulos. Para ello:
Eliminamos el EmployeeModule
y el DepartmentModule
del app.module.ts
, eliminando tanto la declaración de importación de ambos módulos, como los propios módulos del array de import
. Tras estos cambios, nuestro AppModule
quedaría de la siguiente manera:
Después, tenemos que configurar los módulos employee y department como módulos de carga lazy. Para ello, añadimos el siguiente código al app-routing.module.ts
:
Después, añadimos el siguiente código al employee-routing.module.ts
:
Hacemos los mismo con el department-routing.module.ts
y el siguiente código:
Por último, cambiamos el app.component.html
para que, mediante el routerLink
, haga la carga perezosa de nuestros dos módulos.
Volvemos a ejecutar el analizador y comprobamos el tamaño del bundle. Después de implementar la carga perezosa, el tamaño del bundle debería haberse reducido. Sin embargo, podemos ver que ha aumentado en unos 70KB:
Ahora, vamos a eliminar el módulo Material compartido y a importar solamente aquellos módulos que necesitemos. En employee.module.ts
importamos el MatFormFieldModule
y el MatSelectModule
. En el department.module.ts
importamos el MatExpansionModule
y el MatFormFieldModule
. Nos aseguramos de haber borrado el módulo compartido y ejecutamos el comando para analizar el tamaño del bundle. En este ejemplo, deberíamos haber ahorrado unos 40KB aproximadamente.
Conclusión
Hice un experimento similar en mi proyecto actual, y el tamaño del bundle se redujo unos 200KB aproximadamente. Teniendo en cuenta que, en el desarrollo web, cada KB cuenta, os sugeriría el intentar refactorizar vuestra aplicación aplicando lo expuesto en este artículo, y que compartáis vuestra experiencia.
Podéis ver el repositorio de GitHub correspondiente aquí.
Nota de la editora: Este artículo ha sido publicado originalmente por Santosh Yadav en indepth.dev: Stop Using Shared Material Module
Traducción por Estefanía García Gallardo.