Meteor, pour un développement plus rapide qu’une fusée

Meteor, pour un développement plus rapide qu'une fusée

Lancé en 2010 et passé en version 1.0 depuis 2014, ce framework full stack a été pour moi une grande source de découverte et de fun. Encore un énième framework javascript à ajouter dans votre veille, mais ne partez pas tout de suite, celui-ci possède quelques particularités qui pourraient vous donner envie de creuser un peu plus…

Basé sur NodeJS, il est isomorphique et permet donc d’utiliser la même API côté client et serveur.

C’est un outil complet dans le sens où il inclue la base de données, le serveur et des librairies fronts (templating, authentifications…). Le client communique avec le serveur via un protocole appelé DDP, composé de messages JSON envoyés via websocket. Au niveau du code, ces échanges sont mis en place par un mécanisme de publication et souscription des collections Mongo.

Mongo, DDP & miniMongo

Il s’inscrit dans la nouvelle vague des frameworks front, tels que React ou encore Angular, qui cherchent à créer une expérience temps réel. React utilise par exemple des événements et des composants avec changements d’états, Angular un data binding avec le model-view, quant à Meteor c’est la réactivité. Un peu déroutant aux premiers abords, ce principe permet, une fois maîtrisé, de ne plus se soucier de bindings et de mises à jour des vues.

Personnellement, je l’ai trouvé très agréable à utiliser pour la réalisation de POC. Grâce à la synchronisation presque automatique des données et les nombreux packages disponibles. Nous arrivons rapidement à créer de petites applications. Des packages officiels permettent par exemple la gestion des utilisateurs avec l’inscription et la connexion (accounts-ui, accounts-google pour la connexion oauth…).

Première application

Je vous invite à découvrir Meteor un peu plus en détails avec la réalisation d’une mini application de jeu concours. Pour s’amuser encore plus, nous allons utiliser l’API HTML5 Camera. L’application permettra simplement de prendre une photo et de l’ajouter au concours avec son nom.

Les photos seront vos réactions suite à la lecture de cette article et des goodies seront distribués aux photos les plus originales !

JoliSnap

Introduction

La première étape est l’installation de Meteor qui se fait en une ligne.

curl https://install.meteor.com/ | sh

Si vous rencontrez des problèmes, n’hésitez pas à visiter https://www.meteor.com/install.

Vous devriez maintenant posséder le binaire Meteor pour créer un boilerplate d’application. Cette commande va vous créer 3 fichiers (html, css et javascript) avec une simple vue permettant d’augmenter un compteur en cliquant sur un bouton.

meteor create jolisnap

Cette première base nous introduit aux concepts d’isomorphisme et de réactivité. Dans le fichier .js on trouve les conditions Meteor.isServer et Meteor.isClient qui permettent de séparer le code client du code serveur. L’architecture recommandée par le framework est de créer 2 dossiers (serveur et client) pour séparer notre code et un dossier lib pour le code commun.

Le code suivant comprend un helper du template hello qui est une fonction renvoyant la valeur à afficher dans la vue. Nous trouvons aussi un événement click associé au bouton.

Session est un objet disponible sur le client qui est un tableau de stockage mais réactif, c’est à dire qu’il invalide le contexte dans lequel il est compris lors d’un changement de valeur. C’est ce qui permet à la vue de se mettre à jour automatiquement, la fonction counter sera réinvoquée à chaque changement de valeur de Session.get('counter').

// counter starts at 0
  Session.setDefault('counter', 0);

  Template.hello.helpers({
    counter: function () {
      return Session.get('counter');
    }
  });

  Template.hello.events({
    'click button': function () {
      // increment the counter when button is clicked
      Session.set('counter', Session.get('counter') + 1);
    }
  });
}

Nous avons donc créé une application de base qui augmente un compteur en cliquant sur un bouton, pour la lancer encore une simple commande…

meteor

Vous devriez pouvoir accéder au site à l’adresse http://localhost:3000.

Création du concours

La vue

Maintenant que vous connaissez un peu mieux le framework, vous allez pouvoir créer votre première vrai application. Tout d’abord, il est nécessaire de créer le template d’affichage de la liste des photos. La syntaxe est celle de la librairie Blaze, utilisant elle même la syntaxe de Handlebars.

<template name="photos">
    <ul>
      {{#each photos}}
          <li>
              <img src="{{url}}" /> <br />
              {{ name }}
          </li>
      {{/each}}
    </ul>
</template>

Ce template comprend une simple boucle sur un tableau d’objets photos et affiche ces images dans une liste avec le nom de la personne. Nous avons aussi besoin d’une zone pour capturer la vidéo et d’un formulaire pour l’enregistrement du nom. L’appel au template précédent se fait avec la notation {{> photos}}.

<head>
  <title>JoliSnap</title>
</head>

<body>
    <video autoplay></video>
    <canvas style="display:none;"></canvas>
    <br />
    <input type="text" name="name" placeholder="Your name" />

    {{> photos}}
</body>

Modèles, données

Meteor utilise la base de données Mongo par défaut, d’autres systèmes commencent à être utilisés, mais c’est encore au stade expérimental. Pour déclarer une nouvelle collection, nous n’avons besoin que d’une seule ligne.

Photos = new Mongo.Collection("photos");

La variable est globale, ce qui va nous permettre de l’utiliser dans tous nos scripts. Cette déclaration doit être disponible pour le client et le serveur. Une bonne pratique est de la mettre dans un fichier où l’on déclare toutes nos collections. Le simple ajout de cette ligne provoque la synchronisation automatique des données de cette collection sur tous les clients. Pas d’inquiétude, ce mécanisme est rendu possible grâce au package « autopublish » ajouté par défaut lors de la création d’une application. Il est cependant conseillé de gérer la publication / souscription des données manuellement pour des raisons de sécurité évidentes, un message nous invite d’ailleurs à supprimer le package lors du déploiement.

Le présentateur

Pour l’affichage, il est nécessaire de créer un helper correspondant à notre liste de photos, l’API se rapproche très fortement des requêtes mongo. Les méthodes find et findOne sont réactives comme la fonction Session.get, ainsi, à chaque fois qu’une nouvelle photo sera insérée, la vue se mettra à jour automatiquement.

if (Meteor.isClient) {
  Template.photos.helpers({
    photos: function () {
      return Photos.find({}, {sort: {'createdAt': -1}});
    }
  });

  ...
}

Il reste justement à gérer l’ajout des photos via la méthode insert de la collection. Pour que notre code soit exécuté quand le DOM est disponible, il sera placé dans la fonction rendered du template (équivalent de la fonction .ready() de jQuery). Le reste du code correspond à l’API HTML5 avec utilisation des balises videos et canvas pour récupérer une photo de la webcam et la transformer en dataUrl pour l’enregistrement. Si le sujet vous intéresse, j’ai récupéré ces quelques lignes sur html5rocks.

Template.photos.rendered = function() {
  var video = document.querySelector('video');
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('2d');
  var localMediaStream = null;

  function snapshot() {
    if (localMediaStream) {
      ctx.drawImage(video, 0, 0, 400, 150);
      Photos.insert({url: canvas.toDataURL('image/png'), name: $('input').val(), createdAt: new Date});
      video.src = window.URL.createObjectURL(localMediaStream);
    }
  }

  video.addEventListener('click', snapshot, false);
  navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

  navigator.getUserMedia(
    {
      video: true
    },
    function(stream) {
      video.src = window.URL.createObjectURL(stream);
      localMediaStream = stream;
    },
    function() {
      console.log("error getting image");
    }
  );
};

Si votre application fonctionne et que vous souhaitez la déployer, Meteor propose un cloud à la manière d’Heroku pour héberger votre application. Encore une fois c’est très simple:

meteor deploy mybeautifullapp.meteor.com

Si le domaine est disponible, votre code sera publié sur le cloud Meteor. Il est possible de verrouiller ce domaine en l’associant à un compte Meteor developer et ainsi d’autoriser d’autres personnes à publier.

Félicitations, votre application est terminée ! Le code source est disponible sur le dépôt Github, j’ai rajouté quelques styles, un champ email et une validation des données envoyées pour le concours, n’hésitez pas à aller y faire un tour.

N’oubliez pas de participer au concours sur le site JoliSnap !

J’espère que cela vous a donné envie de creuser un peu plus sur ce que permet ce framework. J’aborderai dans de prochains articles plus en détail l’architecture, des bonnes pratiques ou encore la création d’application mobile avec Cordova !

Pour information, voici quelques sites qui l’utilisent déjà en production :

Ressources

Meteor rocks !

blog comments powered by Disqus