Integrating Google Lighthouse in GitLab CI

Our Software Engineers, Ángel Fernández and Pedro Ramírez, detail us how to integrate Google Lighthouse in Continuous Integration processes to optimize applications.

    Artículo elaborado por:

    Ángel Fernández

    Software Engineer en EDICOM

    Desarrollador Full Stack con experiencia en tecnologías Java y JavaScript, apasionado por la arquitectura de software y la gestión del ciclo de vida de las aplicaciones.

    Pedro Ramírez

    Software Engineer en EDICOM

    Arquitecto software y especialista DevOps. Amante de la tecnología y la optimización y automatización de procesos como medio para la mejora continua y calidad global.

Introduction

Performance and usability have gradually become a priority for most companies. At EDICOM, we are convinced that quality and efficiency can go hand in hand. That is why we strive every day to optimize all our applications to enhance the user experience.

There are numerous methods and tools on the market that let you audit a web application, looking for code defects that may compromise quality, expose vulnerabilities and hinder the accessibility of visiting users.

At EDICOM, we have opted to integrate Google Lighthouse in all our Continuous Integration processes due to its quality, power, rollout options and good documentation.

What is Lighthouse?

Lighthouse is an open-source automated tool to audit the performance, usability and quality of a website (loading speed, SEO, PWA, accessibility and other best practices), offering optimization suggestions and guidelines.

Google Lighthouse provides the user with different ways to implement its execution:

  • As an extension in Google Chrome
  • Command line
  • As a module installable in Node
  • Through web UI

Google Lighthouse

Lighthouse installation for local testing

For quick testing, information gathering and auditing of a specific URL, it can be installed locally:

  1. Install current node version: https://nodejs.org/es/
  2. Install Lighthouse using npm.
npm install -g lighthouse

We can now run an audit locally using the command:

lighthouse <url>

To learn about all the available options:

lighthouse – help

Continuous Integration

Optimizing a web application is a task that should not be overlooked. If we do not run audits and generate reports on a regular basis, over time, the integrity and performance of our site may be compromised.

Including Lighthouse in our CI process lets us know the status of our application after each code change and correct possible defects quickly.

For our continuous integration process, we will focus on the command line execution mode.

Docker image creation

To integrate Lighthouse with our GitLab CI, we must generate a Docker image that will allow us to run the necessary commands to audit our website.

Within our image, we will need:

  • Node
  • Chromium
  • Npm
  • Installation by npm:
    • Lighthouse → Allows us to audit our website without generating any kind of report. This is very useful to check the metrics in a “Merge Request” without recording the measurement anywhere.
    • @lhci/cli@0.7.x → Provides a set of tools that lets us run the Lighthouse audit more easily and forward the report to a Lighthouse server. Later we shall explain how to create it.

For this article, a Docker image has been specifically prepared with the necessary resources to run any Lighthouse command in the continuous integration process. All you need to do is apply the GitLab step to the edicom/lighthouse:latest image generated by EDICOM.

  image: edicom/lighthouse:latest

The need may arise to customize or include other resources within the image (Curl, Python2…). Based on the following example, we can generate a Dockerfile to include them:

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

Commands to publish an image to DockerHub from a 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
Feature type branch execution

It is very useful to add a Lighthouse run to each feature type branch generated in GitLab. It will help the maintainability and optimization of the website, allowing us to check in real time that our recent changes do not generate negative metrics.

At EDICOM, the continuous integration process in place runs an automatic deployment of each generated feature-type branch to test the new functionalities quickly. This speeds up the Lighthouse integration process, as it provides us with a URL against which to perform the audit.

Due to resource constraints, it is not usual to maintain a deployment for each feature generated, so in the following example we will apply Lighthouse directly to static files.

We must add the following step to the .gitlab-ci.yml file and enable the stage report in the stages available.

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

It is recommended to use the set of asserts established by Lighthouse, enabling the option –assert.preset=”lighthouse:recommended”.

The “temporary-public-storage” option creates a report in temporary storage provided by Google and remains accessible for seven days. Later we will explain how to create a Lighthouse server to store the audits generated.

Our first audit report is now available.

As an example, metrics are being taken from a very simple web application, generated through the Angular client and without any additional configuration.

At a glance, we can see that it is necessary to improve the loading speed. Google Lighthouse will guide us through the performance optimization process, suggesting changes and providing guidelines to apply to our code.

We can use the links provided to get more detailed information to help us troubleshoot performance issues.

By applying the changes suggested in the report, we will be able to quickly improve our metrics:

Execution in MASTER

For the master branch, a more complete example of integration has been generated, allowing us to build our own Lighthouse server and save the audit reports.

Setting up a Lighthouse server

The following Dockerfile will facilitate the creation of an image that deploys 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 also lets us connect our deployment to a MySQL database. To do so, we must replace the previous entrypoint with:

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

For the archiving of reports, this image must be deployed on a cloud platform and accessible from GitLab.

Generating a new project in Lighthouse Server

Once deployed, we must use the lhci wizard to create a project in which to save the generated report. To do this, you will need to have npm installed locally.

Steps to follow:

  1. First, we open a terminal and install Lighthouse-cli using the command:
npm i -g @lhci/cli

2. Once installed, we run the Lighthouse wizard:

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

  1. Once the setup process has been completed, two tokens will be issued. The admin token must be added to the project configuration.

Connecting GitLab CI and Lighthouse Server

We add the build token with the name LHCI_TOKEN to the variables of the .gitlab-ci.yml file, along with a new step that allows us to launch its execution against the URL of the deployed application.

With the above configuration, a Lighthouse report will be available on the server whenever GitLab detects a change in master.

Application of rules

Lighthouse provides numerous suggestions to improve metrics. Accessing them is quite simple. Just go to the generated report and display the details of the reported errors.

For SEO and accessibility metrics we can take into account the following best practices during development:

Conclusions

The inclusion of Lighthouse in our continuous integration processes has provided, from the outset, an immediate increase in the use of best practices by the development team and a great performance improvement in our applications.

Sometimes, it is difficult to control the minor errors that we introduce in our projects. Lighthouse helps us to achieve an automatic and precise control that allows us to enhance and maintain the quality of our code. In addition, by providing early detection, it avoids product degradations that may require titanic efforts to resolve in the future.

On the other hand, when added to a project that has not followed best practices from the start of its development, the number of improvements it suggests can be rather daunting. For this part, what works best is to plan these improvements and implement them little by little. It is not necessary to optimize everything at once, but it is highly recommended to start doing it.

The complete source code of our examples can be found at GitLab.

Bibliography