Integrar Google Lighthouse en GitLab CI

Nuestros Software Engineers, Ángel Fernández y Pedro Ramírez, nos detallan cómo integrar Google Lighthouse en procesos de Integración Continua para optimizar aplicaciones.

Introducción

El rendimiento y la usabilidad se han convertido lentamente en una prioridad para la mayoría de empresas. En EDICOM, estamos convencidos de que la calidad y la eficiencia no tienen por qué estar reñidas. Por eso nos esforzamos día tras día por optimizar todas nuestras aplicaciones para así mejorar la experiencia de usuario.

Existen numerosos métodos y herramientas en el mercado que permiten auditar una aplicación web, buscando defectos de código que puedan comprometer la calidad, exponer vulnerabilidades y dificultar la accesibilidad de los usuarios que la visitan.

En EDICOM, nos decantamos por integrar Google Lighthouse en todos nuestros procesos de Integración Continua por su calidad, potencia, opciones de ejecución y buena documentación.

¿Qué es Lighthouse?

Lighthouse es una herramienta automatizada open-source que permite auditar el rendimiento, usabilidad y calidad de un sitio web (velocidad de carga, SEO, PWA, accesibilidad y otras buenas prácticas), ofreciendo sugerencias y directrices de optimización.

Google Lighthouse provee al usuario de diferentes formas para implementar su ejecución:

  • Como extensión en Google Chrome.
  • Línea de comandos.
  • Como un módulo instalable en node.
  • Mediante web UI.

Google Lighthouse

Instalación de lighthouse para pruebas locales

Para hacer pruebas rápidas, obtener información y hacer auditorías de una url concreta se puede instalar de manera local:

  1. Instalar la versión actual de node: https://nodejs.org/es/.
  2. Instalar Lighthouse usando npm.
npm install -g lighthouse

Ya podemos hacer una auditoría de manera local mediante el comando:

lighthouse <url>

Para conocer todas las opciones disponibles: 

lighthouse – help

Integración Continua

La optimización de una aplicación web es un trabajo que no se debe descuidar. Si no ejecutamos auditorías y generamos informes de manera regular, con el tiempo, la integridad y rendimiento de nuestro sitio pueden quedar comprometidos.

Incluir Lighthouse en nuestro proceso de CI nos permite conocer el estado de nuestra aplicación tras cada cambio de código y corregir posibles defectos rápidamente.

Para nuestro proceso de integración continua nos centraremos en el modo de ejecución por línea de comandos.

Creación de imagen Docker

Para poder integrar Lighthouse con nuestro GitLab CI debemos generar una imagen de Docker que nos permita ejecutar los comandos necesarios para auditar nuestra página web.

Dentro de nuestra imagen necesitaremos:

  • Node
  • Chromium
  • Npm
  • Instalar mediante npm:
    •  Lighthouse → nos permitirá hacer una auditoría de nuestra web sin generar ningún informe de reporte, esto es muy útil para comprobar las métricas en un “Merge Request” sin que quede registrada la medición en ningún sitio.
    • @lhci/cli@0.7.x → nos proporciona un conjunto de herramientas que nos permite ejecutar de manera más sencilla la auditoría de Lighthouse y enviar el informe a un servidor de Lighthouse. Posteriormente explicaremos cómo crearlo.

Para este artículo, se ha preparado específicamente una imagen Docker con los recursos necesarios para ejecutar cualquier comando de Lighthouse en el proceso de integración continua. Bastaría con apuntar el step de GitLab contra la imagen edicom/lighthouse:latest generada por EDICOM.

  image: edicom/lighthouse:latest

Puede surgir la necesidad de querer personalizar o incluir otros recursos dentro de la imagen (Curl, Python2…). A partir del siguiente ejemplo podemos generar un archivo Dockerfile para incluirlos:

FROM alpine
LABEL maintainer = 'EDICOM'

RUN apk add – no-cache bash && \
    apk add – update nodejs npm && \ 
    apk add – no-cache chromium

RUN npm install -g lighthouse
RUN npm install -g @lhci/cli@0.7.x

Comandos para publicar una imagen en DockerHub a partir de un Dockerfile:

cd /path/to/Dockerfile
docker build .
docker images
docker tag local-image:tagname new-repo:tagname
docker login
 → dockerhub user
 → dockerhub password
docker push new-repo:tagname
Ejecución en ramas de tipo feature

Es muy útil añadir una ejecución de Lighthouse a cada rama de tipo feature generada en GitLab. Ayudará a la mantenibilidad y optimización de la web, permitiendo comprobar en tiempo real que nuestros cambios recientes no generan métricas negativas.

En EDICOM, el proceso de integración continua establecido ejecuta un despliegue automático de cada rama de tipo feature generada para poder probar las nuevas funcionalidades rápidamente, esto agiliza el proceso de integración de Lighthouse, ya que nos provee de una url contra la que realizar la auditoría.

Por limitación de recursos, no suele ser habitual mantener un despliegue por cada feature generada, por lo que en el siguiente ejemplo apuntaremos Lighthouse directamente contra ficheros estáticos.

Debemos añadir el siguiente step al fichero .gitlab-ci.yml y habilitar el stage report en los stages disponibles.

stages:
  - report

static_review_report:
  stage: report
  image: edicom/lighthouse:latest
  script:
    - npm install
    - npm run build:prod
    - lhci autorun – upload.target=temporary-public-storage – collect.settings.chromeFlags="--no-sandbox" – assert.preset="lighthouse:recommended" || echo "LHCI failed!"
  allow_failure: true
 except:
   refs:
     - master

Es recomendable utilizar el conjunto de asserts establecidos por Lighthouse habilitando la opción –assert.preset=”lighthouse:recommended«. 

La opción “temporary-public-storage” genera un informe en un almacenamiento temporal proporcionado por Google y se mantiene accesible durante siete días. Más adelante explicaremos cómo crear un servidor de Lighthouse para almacenar las auditorías generadas.

Ya tenemos disponible nuestro primer informe de auditoría.

A modo de ejemplo, se están obteniendo métricas de una aplicación web muy simple, generada a través del cliente de Angular y sin ningún tipo de configuración adicional.

De un simple vistazo, podemos observar que es necesario mejorar la velocidad de carga. Google Lighthouse nos guiará en el proceso de optimización de rendimiento, sugiriendo cambios y proporcionando directrices a aplicar en nuestro código.

Podemos hacer uso de los enlaces proporcionados para obtener información más detallada que nos ayude a solventar los problemas de rendimiento.

Aplicando los cambios sugeridos en el informe podremos mejorar rápidamente nuestras métricas:

Ejecución en MASTER

Para la rama master se ha generado un ejemplo más completo de integración, que nos permita levantar un servidor propio de Lighthouse y almacenar los informes de auditoría.

Levantando un servidor de Lighthouse

El siguiente fichero Dockerfile, nos facilitará la creación de una imagen que despliegue Lighthouse Server:

FROM alpine
LABEL maintainer = 'EDICOM'

RUN apk add – no-cache bash && \
         apk add – update nodejs npm && \
         apk add – no-cache python2

RUN npm -g config set user root
RUN npm install -g @lhci/cli @lhci/server mysql2 sqlite3

RUN mkdir /config-properties

ENTRYPOINT ["lhci", "server", "--port", "8080", "--storage.storageMethod=sql", "--storage.sqlDialect=sqlite", "--storage.sqlDatabasePath=/config-properties/db.sql"]

Lighthouse Server también nos permite conectar nuestro despliegue con una base de datos en MySQL, para ello debemos sustituir el entrypoint anterior por:

ENTRYPOINT ["lhci", "server", "--port", "8080", "--storage.storageMethod=sql", "--storage.sqlDialect=mysql", "--storage.sqlConnectionUrl=mysql://<user>:<password>@<url>/<database>"]

Para el almacenamiento de los informes, esta imagen deberá estar desplegada en alguna plataforma cloud y accesible desde GitLab.

Generar un nuevo proyecto en Lighthouse Server

Una vez desplegado, debemos usar el lhci wizard para crear un proyecto donde almacenar el informe generado. Para ello, será necesario tener instalado npm localmente.

Pasos a seguir:

  1. En primer lugar, abrimos una terminal e instalamos Lighthouse-cli mediante el comando:
npm i -g @lhci/cli

2. Una vez instalado, ejecutamos el asistente de Lighthouse:

lhci wizard

Wich wizard do you want to run? new-project
Watch is the URL of your LHCI server? url al servidor desplegado de lighthouse
What would you like to name the project? Nombre del proyecto a generar
Where is the project's code hosted? Podemos incluir la url de gitlab si el proyecto es público o dejarlo con la configuración por defecto.
What branch is considered the repo's trunk or main branch? master

3. Una vez terminado el proceso de configuración, dos tokens serán expedidos, el admin token debe ser añadido en la configuración del proyecto.
https://<url-lighthouse-server>/app/projects/<<project-name>>/settings

Conectar GitLab CI y Lighthouse Server

El build token lo añadiremos con el nombre LHCI_TOKEN en las variables del archivo .gitlab-ci.yml junto a un nuevo step que nos permita lanzar su ejecución contra la URL de la aplicación desplegada.

variables:
  URL: https://<url-applicacion>
  LHCI_TOKEN: 587acafb-8a01-4aa1-9e=c-d902c661b10a

stages:
  - report

static_review_report:
  stage: report
  image: edicom/lighthouse:latest
  script:
    - lhci autorun – upload.target="lhci" – upload.token="$LHCI_TOKEN" – upload.serverBaseUrl="https://<url-lighthouse-server>" – collect.url="$URL" – collect.settings.chromeFlags="--no-sandbox – headless – ignore-certificate-errors" || exit 1
  rules:
    - if: “$CI_COMMIT_REF_NAME !~ /master/”

Con la configuración anterior, quedará disponible un informe de Lighthouse en el servidor cada vez que GitLab detecte un cambio en master.

Aplicación de reglas

Lighthouse proporciona numerosas sugerencias para mejorar las métricas. Acceder a ellas es bastante sencillo, basta con ir al informe generado y desplegar los detalles de los errores reportados.

Para las métricas de SEO y accesibilidad podemos tener en cuenta las siguientes buenas prácticas durante el desarrollo:

  • Incluir todas las etiquetas de metadatos en la cabecera de nuestra aplicación (meta, title, description, author, theme-color…).
  • Estructurar bien los títulos, no debemos saltarnos etiquetas de tipo h1, h2, h3…
  • Incluir un fichero robots.txt válido, podemos validarlo en https://www.google.com/webmasters/tools/robots-testing-tool.
  • Todas las imágenes deben contener el atributo ALT con una descripción específica. También es recomendable que tengan definido un ancho y un alto.
  • Evitar que la consola lance errores que puedan ser controlados.
  • Todos los botones deben contener el atributo aria-label para permitir la accesibilidad.
  • Evitar cargar dependencias no utilizadas en nuestro proyecto. Esto generará retrasos innecesarios en la carga inicial de nuestra aplicación.
  • Utilizar colores que generen un buen contraste y permitan la diferenciación.
  • Utilizar tamaños de fuente legibles.
  • Mejorar los tiempos de carga inicial utilizando módulos de tipo lazy.

Conclusiones

La inclusión de Lighthouse en nuestros procesos de integración continua ha proporcionado, desde el primer momento, un incremento inmediato del uso de buenas prácticas por parte del equipo de desarrollo y una gran mejora de rendimiento en nuestras aplicaciones.

En ocasiones, es difícil controlar los pequeños errores que vamos introduciendo en nuestros proyectos, Lighthouse nos ayuda a obtener un control automático y preciso que nos permite aumentar y mantener la calidad de nuestro código. Además, al proporcionar una detección temprana, evita degradaciones del producto que a futuro pueden necesitar esfuerzos titánicos para ser solventadas.

Por otro lado, cuando se añade en un proyecto que no ha seguido buenas prácticas desde el principio de su desarrollo, puede asustar un poco la cantidad de mejoras que sugiere. Para esta parte lo que mejor funciona es planificar dichas mejoras y aplicarlas poco a poco. No es necesario optimizar todo de golpe, pero sí es muy recomendable empezar a hacerlo.

El código fuente completo de nuestros ejemplos se encuentra en GitLab.

Bibliografía