Je passe beaucoup de temps à faire des prototypes de projets, j’ai le fameux syndrôme du projet perso, je ne compte même plus le nombre de repos que j’ai sur Github ou Gitlab. Très peu d’entre eux sont terminés, mais c’est le but en fait d’un projet perso.

Quelques projets ont la chance d’être déployés et une infime partie ont même la chance d’avoir des utilisateurs !

En revanche aucun projet n’est monétisé, pourtant j’utilise des serveurs, de l’hébergement, des bases de données, etc : comment je fais ?

À part 3-4 noms de domaines (environ 50€), je ne dépense pas d’argent. J’en dépenserai pour un projet quand celui-ci sera voué à devenir mon activité principale. En attendant, j’utilise des solutions Saas gratuites et j’y trouve mon compte.

Je vais vous lister celles que j’utilise sur mes projets.

Firebase

Firebase fait tout ! On pourrait se contenter seulement de firebase.

Firebase c’est l’ensemble de services proposés par Google. Les services sont gratuits avec des quotas d’utilisation dans la formule de base, autrement, ça fonctionne comme n’importe quel cloud provider, vous payerez ce que vous consommez.

Vous y retrouverez :

  • des bases de données (Firestore),
  • de l’authentification,
  • des notifications,
  • de l’hébergement,
  • et bien d’autres services.

Firebase propose une documentation complète qui vous aide pour intégrer les différents services sur votre application. La communauté est active, parfait si vous êtes bloqué.

Firebase propose un SDK pour les projets en Javascript, avec la version 9, npm firebase , qui a été release cette année, les équipes de Google apportent des API modulaires pour manipuler Firebase. Vous avez notamment le tree-shaking qui vous permet de conserver une application la plus petite et rapide possible.

Concrètement à quoi ressemble l’utilisation de firebase ?

Voici un petit exemple sur un de mes projets qui me permet d’uploader des photos et de stocker le lien permettant de les récupérer.

const id = "123";
const cameraImage =
  "data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB";

// Créer une réference vers mon fichier 'posts/123'
const storageRef = ref(storage, `posts/${id}`);
// Upload du fichier vers ma référence 'posts/123'
uploadString(storageRef, cameraImage, "data_url")
  // UploadString est une Promesse, peut aussi retourner une UploadTask.
  .then((snapshot) => {
    // Upload réussi, on peut récupérer l'URL de téléchargement
    getDownloadURL(snapshot.ref).then((downloadURL) => {
      // Sauvegarde de l'URL dans une collection de 'posts'
      addDoc(collection(db, "posts"), {
        imageUrl: downloadURL,
        username: "Cyril",
        read: false,
        timestamp: serverTimestamp(),
      });
    });
  })
  .catch((error) => {
    // error function
    console.log(error);
  });

Expliquons cet exemple, nous avons une image encodée en base64 qui est une chaine de string. Nous allons uploader dans le service de storage de firebase notre image.

uploadString(storageRef, cameraImage, "data_url", null);
//              ^             ^          ^          ^
//              |             |          |          |
//             (a)           (b)        (c)        (d)
// a : la référence de mon document, là où sera stocké le document
// b : la string à upload
// c : (optionel) - le format de la string uploadé
// d : (optionel) - Metadata à ajouter

uploadString est une promesse, nous pouvons donc ajouter un then(), nous avons accès à un UploadResult, ici l’objet snapshot, ce qui nous permet d’avoir la ref de notre image uploadée.

Firebase nous met à disposition la méthode getDownloadURL(ref) qui est une promesse et nous renvoit la downloadUrl du fichier, c’est l’url public qui permet d’accéder à l’image.

Nous allons sauvegarder cette url pour pouvoir l’obtenir à l’avenir plus facilement au travers de notre application. On a plus qu’à ajouter cette url dans un document que l’on stocke dans firestore.

Et voilà !

Il reste encore plein de choses à découvrir avec l’utilisation de firebase : j’aime par exemple utiliser ce service pour la partie authentification des utilisateurs. Firebase propose un large choix de moyens d’authentification qui sont très simples à implémenter sur vos projets.

Firebase propose une CLI, parfait pour mettre en place un pipeline de déploiement continu.

Netlify

Vous pouvez héberger vos projets via Firebase ou même avec Gitlab Pages, mais personnellement j’aime utiliser Netlify, d’ailleurs mon blog est hébergé grâce à leurs services. Ils proposent une intégration avec Gitlab, Github et Bitbucket, la configuration par défaut déclenchera un déploiement à chaque commit sur votre branche main. C’est un bon début pour s’initier au déploiement continu.

Du côté de Gitlab ça se caractérise par un pipeline external.

Dans les autres services proposés par Netlify il y a les Forms, je vous laisse cet article de Brian Li qui vous explique comment utiliser le service avec un blog en Hugo 👌.

MongoDb & Heroku

Si vous voulez mettre une Api à disposition par exemple un CRUD, j’aime utiliser le combo MongoDb et Heroku. MongoDb vous permet d’héberger une base de données, avec une limitation de taille, mais pour des petits projets c’est suffisant. Après avoir configuré et importé vos données, vous n’aurez plus qu’à utiliser la connection string dans votre code.

// Exemple d'utilisation dans mon Api GraphQl
const mongoConnectString =
  process.env.NODE_ENV === "production"
    ? process.env.MONGO_DB_CONNEXION_STRING
    : "mongodb://localhost:27017/magic-tools";

Heroku permet de déployer des serveurs gratuitement, j’ai par exemple une API en GraphQl déployée chez Heroku. Vous aurez accès à une CLI qui permet d’intégrer Héroku dans vos pipelines Gitlab. Les serveurs d’Heroku fonctionnent on-demand en version gratuite, ils ne seront up que lorsqu’ils sont sollicités : cela peut entrainer des petits délais au démarrage mais rien de dérangeant.

image: node:latest

before_script:
  - apt-get update -qy
  - apt-get install -y ruby-dev
  - gem install dpl

stages:
  - production

production:
  type: deploy
  stage: production
  image: ruby:latest
  script:
    - dpl --provider=heroku --app=$HEROKU_APP_PRODUCTION --api-key=$HEROKU_API_KEY --skip-cleanup
  only:
    - master