Artículo elaborado por:
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
Lighthouse installation for local testing
For quick testing, information gathering and auditing of a specific URL, it can be installed locally:
- Install current node version: https://nodejs.org/es/
- Install Lighthouse using npm.
npm install -g lighthouse
We can now run an audit locally using the command:
To learn about all the available options:
lighthouse – help
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:
- 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.
- @firstname.lastname@example.org → 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.
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 @email@example.com
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:
- 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
- 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.
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/”
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:
- Include all the metadata tags in the header of our application (meta, title, description, author, theme-colour …).
- Structure the titles properly; we must not skip h1, h2, h3… type tags.
- Include a valid robots.txt file. We can validate it at https://www.google.com/webmasters/tools/robots-testing-tool.
- All images must contain the ALT attribute with a specific description. It is also advisable to have a width and height defined.
- Prevent the console from launching errors that can be controlled.
- All buttons must contain the aria-label attribute to allow accessibility.
- Avoid loading dependencies not used in our project. This will give rise to unnecessary delays in the initial loading of our application.
- Use colours that generate good contrast and allow differentiation.
- Use readable font sizes.
- Improve the initial loading times by using lazy modules.
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.
- Lighthouse https://github.com/GoogleChrome/lighthouse
- Lighthouse CI https://github.com/GoogleChrome/lighthouse-ci