Optimiza el CSS con cssnano

Foto de Pankaj Patel en Unsplash

Si bien al escribir nuestras hojas de estilos podemos ayudarnos de herramientas como Stylelint y a la hora de llevar a producción nuestro proyecto de Angular activamos la opción de optimización, siempre podemos mejorar un poco más el resultado de la optimización gracias a la librería cssnano. No lo dudes, optimiza el CSS con cssnano.

La librería cssnano obtiene tu CSS bien formateado y lo ejecuta a través de muchas optimizaciones específicas, para garantizar que el resultado final sea lo más pequeño posible para un entorno de producción. Además, admite configuraciones personalizadas mediante ajustes preestablecidos que controlan el nivel de optimización que desees. Tecnológicamente, cssnano funciona con PostCSS, una herramienta para transformar estilos con JavaScript. Específicamente, su arquitectura de complementos nos permite componer cssnano a partir de pequeños módulos con responsabilidades limitadas. También le permite insertar fácilmente cssnano en su paso de compilación, junto con otros procesadores que pueden detectar errores en su CSS o transpilar sintaxis futura.

Ajustes preestablecidos

Como se ha comentado anteriormente, dispone de tres «presets» de optimizaciones para que solamente tengas que seleccionarlo sin necesidad de especificar cada regla:

Aquí te dejo el cuadro de presets con sus respectivas reglas activadas. Con el preset default hay más que suficiente para mejorar el css final.

Te invito a que visualices algunas optimizaciones:

Utilizando cssnano en Angular

Si ya tienes tu proyecto de Angular creado, hay que instalar la librería al package.json de la siguiente manera:

npm install --save-dev cssnano 

Normalmente en el proyecto de Angular ya viene instalada la librería postcss. Si estás en otro tipo de proyecto deberías instalar también postCSS.

Ahora solo hace falta añadir un archivo de configuración de postCSS en la raíz del proyecto (donde esté ubicado el angular.json) seleccionando el preset que más nos convenga. En el ejemplo tomaremos el preset default.

El nombre del archivo de configuración debe llamarse «postcss.config.json» ó «.postcssrc.json» (lo dejo a tu elección). y el contenido debería ser el siguiente (dependiendo de si ya tenías una configuración previa de postcss):

{
  "plugins": {
    "cssnano": {
      "preset": "default"
    }
  }
}

Ahora ya, cada vez que realices el build se ejecutará automáticamente el proceso de optimización con cssnano. Puedes comprobar el antes y el después de la optimización (sobre todo comparar el espacio que ocupa el archivo css) así como si funciona correctamente. Naturalmente puedes modificar la configuración de cssnano activando o desactivando reglas de optimización.

Resultados

Partimos de dos archivos de estilos en formato scss:
Archivo «_functions.scss:

.flex {
    display:flex;
}

.horizontal-list {
  flex-wrap: wrap;
  justify-content: space-between;
  list-style: none;
  padding: 0;
  margin: 0;
  li {
    margin-bottom: 1rem;
  }
}

.vertical-list {
  display: flex;
  flex-direction: column;
  list-style: none;
  padding: 0;
  margin: 0;
  li {
    margin-bottom: 1rem;
  }
}

Archivo «styles.scss»:

@use "functions" as *;

.include {
    /*test*/
    @extend .flex;
    @extend .horizontal-list;
}

.block {
    padding-right:5px;
    padding-left:5px;
    padding-top: 0px;
    padding-bottom: 0px;
}

.block {
    padding-left:5px;
}

.empty {}

.example {
    display: grid;
    transition: all .5s;
    user-select: none;
    background: linear-gradient(to bottom, white, black);
}

Ahora, si realizamos el build en modo producción, sin la optimización obtenemos el siguiente resultado:

Captura pantalla salida por consola compilación sin optimización css
Salida de la compilación de Angular sin optimización de CSS

El contenido del archivo css resultante es el siguiente:

.flex,.include{display:flex}.horizontal-list,.include{flex-wrap:wrap;justify-content:space-between;list-style:none;padding:0;margin:0}.horizontal-list li,.include li{margin-bottom:1rem}.vertical-list{display:flex;flex-direction:column;list-style:none;padding:0;margin:0}.vertical-list li{margin-bottom:1rem}.block{padding:0 5px}.block{padding-left:5px}.example{display:grid;transition:all .5s;user-select:none;background:linear-gradient(to bottom,#fff,#000)}

Con la optimización obtenemos el siguiente resultado:

Salida por pantalla de la compilación de Angular con optimización del css mediante cssnano
Salida de la compilación de Angular con optimización de CSS mediante cssnano con preajuste en «default»

El contenido del archivo css resultante es el siguiente:

.flex,.include{display:flex}.horizontal-list,.include{flex-wrap:wrap;justify-content:space-between;list-style:none;margin:0;padding:0}.horizontal-list li,.include li{margin-bottom:1rem}.vertical-list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}.vertical-list li{margin-bottom:1rem}.block{padding:0 5px}.example{background:linear-gradient(180deg,#fff,#000);display:grid;transition:all .5s;user-select:none}

Vemos que algo sí ha mejorado, hemos pasado de 459 bytes a 432 bytes, es decir, un ahorro de 27 bytes con este ejemplo sencillo. No obstante en un proyecto grande donde hay muchísimos más hojas de estilos el ahorro puede ser mucho mayor.
En nuestro caso concreto, ha optimizado la clase «.block» que estaba repetida (24 bytes) así como el estilo «.example» con el linear-gradient (3 bytes).

Por contra el proceso de build se alarga un poco más al ejecutar este paso, en el ejemplo hemos pasado de unos 5.075 segundos a 5.612, es decir, el proceso se ha alargado medio segundo (en cada proceso se ha ejecutado en la misma máquina eliminando la cache «.angular» y «dist»).

Entradas relacionadas

Utilidades npm: rimraf, alternativa al comando Unix rm -rf 

por César Marín
11 meses atrás

Multi-idioma de los recursos (Parte 1)

por César Marín
6 años atrás

Directive composition API

por César Marín
3 meses atrás
Salir de la versión móvil