
Vous en avez assez de déployer manuellement votre site Nuxt ? Dans cet article, je vous montre comment automatiser l’ensemble du processus grâce à GitLab CI/CD, du commit jusqu’à la mise en ligne.
Rappel technique concernant Nuxt
Nuxt est un framework JavaScript que j'utilise beaucoup ces derniers temps. Il est facile à mettre en place et permet de réaliser des sites web dynamiques, rapides et performants. J'apprécie beaucoup le fait que l'on puisse compiler le projet pour générer des fichiers statiques prêts à être déposés sur un hébergement tout simple. C'est ce que l'on appelle le mode SSG (Static Site Generation).
Cette façon d'utiliser Nuxt me permet de déployer des sites très rapides à charger même lorsqu'ils contiennent des images volumineuses. Les images sont automatiquement optimisées et déclinées en plusieurs tailles selon la largeur d’écran.
Lorsque le visiteur charge le site, il récupère directement le HTML, le JS et le CSS. Il n'y a aucun traitement réalisé côté serveur. C'est comme si le site était perpétuellement en cache sur le serveur.
Comment se passe alors une mise à jour de contenu ?
Ce type de site est adapté aux projets où il y a très peu de mises à jour. Cela peut être un site vitrine, un portfolio ou un site de chambres d'hôtes. Comme il n'y a pas d'interface admin, il est donc nécessaire de toucher au code, de recompiler le site puis de redéployer le site sur le serveur. Cela n'est pas très pratique, mais heureusement, il est possible d'automatiser tout cela si vous utilisez Git et notamment Gitlab.
Découverte et mise en place de GitLab CI
Que ce soit chez GitHub ou Gitlab, le concept de CI (pour intégration continue) permet de déclencher des traitements automatiques lors d'un commit Git. Les opérations se font dans un container et peuvent être diverses et variées : vérification du code, compilation et envoi vers un serveur FTP distant par exemple. Pile-poil ce dont j'avais besoin !
Le point d'entrée de la CI chez Gitlab est le fichier .gitlab-ci.yml, à la racine du projet. On va décrire, au format YAML, les différentes étapes qui seront réalisées lors d'un commit. Voici un premier point d'entrée :
stages:
- build
- deploy
Ici, on a donc deux étapes qui seront réalisées les unes après les autres. Ensuite, on va pouvoir décrire chacune de ces étapes. Par exemple, l'étape du build
:
build:
stage: build
image: node:22
script:
- npm ci --cache .npm --prefer-offline
- npm run generate
artifacts:
paths:
- .output/public
On utilise ici une image en Node v22 comme environnement d'exécution et on va lancer deux commandes :
npm ci
pour installer les dépendances de notre projet ;npm run generate
pour créer la version SSG de notre application.
Ici j'utilise
npm ci
plutôt quenpm i
. Node utilise alors le fichier package-lock.json pour installer toutes les dépendances d'un coup. C'est le plus adapté aux environnements automatisés comme l'intégration continue.
Les artifacts sont les données qui sont passées d'une étape à l'autre. Ici j'ai mis le dossier qui contient le site compilé.
L'étape deploy
consiste donc à déployer le résultat de l'étape précédente sur un serveur distant. Pour cela, j'ai utilisé l'outil lftp
qui permet de transférer les fichiers.
deploy:
stage: deploy
timeout: 10 minutes
script:
- apt-get update -qq && apt-get install -y -qq lftp
- lftp -e "set sftp:auto-confirm yes; mirror -R ./.output/public/ /home/site/www; quit" -u utilisateur,m0td3p4ss3 sftp://ftp.herbergement.fr
only: [ master ]
Le paramètre
only
permet d'indiquer que seuls les commits de la branche master seront déployés sur le serveur distant.
Une alarme a sûrement sonné dans votre tête : les informations de connexion au serveur FTP sont en clair dans le fichier .gitlab-ci.yml. Heureusement, il est possible de les rendre invisibles via la gestion des secrets de Gitlab.
Gestion des secrets
Sur Gitlab, il faut se rendre dans Paramètres > CI/CD
puis dans la section Variables de projet.
Dans mon cas, j'ai ajouté les variables suivantes :
DEPLOY_HOST
: l'hôte du serveur FTP auquel se connecter ;DEPLOY_USER
: l'identifiant de connexion ;DEPLOY_PASSWORD
: le mot de passe de connexion ;DEPLOY_PATH
: le chemin où déposer les fichiers.
Pensez à protéger les variables en les masquant et en cachant le mot de passe.
On peut donc mettre à jour notre fichier .gitlab-ci.yml. Le voici au complet à ce stade :
stages:
- build
- deploy
build:
stage: build
image: node:22
script:
- npm ci --cache .npm --prefer-offline
- npm run generate
artifacts:
paths:
- .output/public
deploy:
stage: deploy
timeout: 10 minutes
script:
- apt-get update -qq && apt-get install -y -qq lftp
- lftp -e "set sftp:auto-confirm yes; mirror -R ./.output/public/ $DEPLOY_PATH; quit" -u $DEPLOY_USER,$DEPLOY_PASSWORD sftp://$DEPLOY_HOST
only: [ master ]
Tests et peaufinage
C'est le moment de tester ! Commencez par commit le fichier .gitlab-ci.yml puis effectuez un git push
. Dans Gitlab, tout ce qui concerne le déploiement continu est dans le menu Compilation. On y retrouve les jobs (chaque étape définie dans le YAML), mais également les pipelines qui regroupent ces jobs pour chaque commit. Un éditeur de pipeline permet de modifier directement en ligne notre fichier .gitlab-ci.yml !
Lorsqu'il y a une erreur, on peut consulter le détail du job concerné et observer la sortie du terminal. En général, après quelques itérations, on obtient une intégration continue fonctionnelle !
Aller plus loin avec les environnements
Tout ceci est chouette, mais il est fréquent d'avoir plusieurs branches et plusieurs destinations où déployer son code. Par exemple, un environnement de test / pré-prod / staging ne devrait se mettre à jour qu'avec le travail de la branche dev, là où l'environnement de production ne devrait se mettre à jour qu'avec le code de la branche main ou master. Eh bien, c'est possible !
Dans Gitlab, on se rend dans Opération > Environnement
et on crée deux environnements : dev et prod. Ensuite, dans la configuration des variables (Paramètres > CI/CD
), on va pouvoir définir une valeur différente pour chacun des environnements.
Dans mon cas, j'ai défini un
DEPLOY_PATH
différent pour mes deux environnements, parce que mon environnement de développement et mon environnement de production sont sur la même machine. Rien ne vous empêche de configurer des utilisateurs, mots de passe et hôtes différents !
On peut ensuite adapter notre fichier .gitlab-ci.yml pour tenir compte de ces environnements :
stages:
- build
- dev
- prod
build:
stage: build
image: node:22
script:
- npm ci --cache .npm --prefer-offline
- npm run generate
artifacts:
paths:
- .output/public
dev:
stage: dev
environment: Dev
timeout: 10 minutes
script:
- apt-get update -qq && apt-get install -y -qq lftp
- lftp -e "set sftp:auto-confirm yes; mirror -R ./.output/public/ $DEPLOY_PATH; quit" -u $DEPLOY_USER,$DEPLOY_PASSWORD sftp://$DEPLOY_HOST
except: [ master ]
prod:
stage: prod
environment: Prod
timeout: 10 minutes
script:
- apt-get update -qq && apt-get install -y -qq lftp
- lftp -e "set sftp:auto-confirm yes; mirror -R ./.output/public/ $DEPLOY_PATH; quit" -u $DEPLOY_USER,$DEPLOY_PASSWORD sftp://$DEPLOY_HOST
only: [ master ]
On a donc maintenant trois jobs :
build
, qui se charge de compiler le site ;dev
, qui utilise l'environnement « Dev » pour les variables et qui sera lancé sur toutes les branches sauf master ;prod
, qui utilise l'environnement « Prod » et qui ne se déclenchera que pour les commits sur la branche master.
De cette façon, lorsque nous faisons un commit, c'est automatiquement déployé sur un environnement ou l'autre.
Ce que ça change au quotidien
Si je prends l'exemple du site sur lequel vous lisez cet article, une bonne partie du contenu est rédigée en Markdown et affichée à l'aide du module Nuxt Content . Pour le mettre à jour, j'ai simplement besoin d'un éditeur de texte et de réaliser un commit. Le reste se fait automatiquement, sans que j'aie à y penser.
Bonus : il y a directement dans Gitlab un éditeur de code, je peux donc éditer mon contenu même en déplacement tant que j'ai accès à mon compte.
Si l'on travaille seul, mais que l'on travaille sur de multiples projets, avec des technos différentes et surtout des versions de Node différentes, cela simplifie grandement le travail : toute la procédure de déploiement est consignée dans un fichier et est exécutée automatiquement.
Si l'on travaille à plusieurs, c'est aussi un avantage : on n'a pas à expliquer comment mettre à jour le site et encore moins à partager les informations de connexion. C'est aussi l'endroit parfait pour ajouter les tests unitaires, du linting et d'autres automatismes !