Jamstack & Gitlab Pages

Publié il y a plus d’un an~3 min

Le développement des générateurs de sites statiques (SSG) s'est largement renforcé ces dernières années, avec la promesse de sites web plus performants, plus sûrs et plus faciles à héberger. Un simple CDN peut suffire, ce qui simplifie alors d'autant plus la publication de son projet sur le web.

Gitlab met à disposition gratuitement un hébergement statique pour chaque dépôt de code. Alors pourquoi ne pas en profiter pour y héberger notre projet Jamstack ?

Sur la base d'un projet Next.js, nous allons voir comment configuer la CI/CD de Gitlab, grâce au fichier .gitlab-ci.yml et à quelques ajustements, pour déployer directement sur Gitlab Pages !

Pré-requis

  1. Node.js (>= 10.13)
  2. Un compte Gitlab 😲

Un projet de démonstration a été créé dans le cadre de cet article, n'hésitez donc pas à vous y référer pour plus de détails (scripts, ...) !

Création du projet

Next.js nous permet de créer rapidement un nouveau projet, grâce aux commandes suivantes :

1npx create-next-app
2# ou
3yarn create next-app

La documentation du site est plutôt complète, et leur dépôt Github regorge d'informations et d'exemples.

Configuration du projet

Gitlab Pages propose par défaut des urls spécifiques à chaque type de page :

  1. S'il s'agit d'une page d'utilisateur ou de groupe (le nom du dépôt est <username|groupname>.gitlab.io), l'url du site est alors https://<username|groupname>.gitlab.io/
  2. S'il s'agit d'une page de projet (issu d'un utilisateur ou d'un groupe), alors l'url devient https://<username|groupname>.gitlab.io/<projectname>/

Next.js (comme tous les SSG) n'ayant pas connaissance de cette spécificité, il peut donc s'avérer nécessaire, le cas échéant, d'indiquer le domaine sur lequel il se situe, afin que les liens des assets exportés (dans le dossier _next) ne soient pas brisés. 💔

Ainsi dans le cas d'une page de projet, il faudra simplement préciser le nom de celui-ci en valeur du paramètre assetPrefix :

1const isProd = process.env.NODE_ENV === 'production'
2
3module.exports = {
4 assetPrefix: isProd ? '/<projectname>/' : ''
5}

A noter que pour préserver nos liens en environnement local (développement), on utilisera la variable d'environnement Node pour définir plus spécifiquement ce paramètre.

Le fichier Gitlab

Gitlab Pages s'active automatiquement en présence d'un fichier .gitlab-ci.yml comportant une entrée pages.

Outre ce fichier de configuration, il faudra aussi s'assurer de la visibilité du site dans les paramètres du dépôt (dans Paramètres > Général > Visibilité).

Et voici donc le fichier tant attendu :

1image: node
2
3cache:
4 paths:
5 - node_modules/
6
7pages:
8 before_script:
9 # Clean public folder
10 - find public -mindepth 1 -maxdepth 1 -type d | xargs rm -rf
11 - find public -type f -name "*.html" | xargs rm -rf
12 # Install packages
13 - npm install
14 script:
15 # Build application and move content to public folder
16 - npm run publish
17 - mv out/* public
18 after_script:
19 # Cleanup
20 - rm -rf out
21 artifacts:
22 paths:
23 - public
24 only:
25 - master

La particularité de ce déploiement réside dans les contraintes de Gitlab Pages et de Next.js : le premier accepte pour seul point d'entrée un dossier public... qui est aussi un dossier réservé pour le second, et dans lequel on ne peut donc pas faire nos exports ! 🤯

La solution proposée ici, est donc de découper notre script en trois phases :

  1. On s'assure que le dossier public soit nettoyé de tous les fichiers et/ou dossiers résiduels (sans quoi Next.js refusera d'exporter le projet), puis on installe les packages

  2. On compile et on exporte notre projet sous formes de pages statiques, avant de déplacer le contenu généré dans le dossier public (à disposition de Gitlab)

  3. Une fois ces deux étapes terminées, on supprime le dossier d'export de Next.js (par défaut out)

🎉

Et voilà ! Malgré une petite gymnastique imposée par les contraintes respectives de Gitlab Pages et Next.js, le fichier reste simple et lisible ! 💪 Nous voici désormais libres de publier nos contenus rapidement, sans s'embarraser d'un service supplémentaire et superflu ! 🙂