Skip to content

Instantly share code, notes, and snippets.

@sandhose
Last active August 29, 2015 14:13
Show Gist options
  • Save sandhose/3fe03dd883ba2c5a6132 to your computer and use it in GitHub Desktop.
Save sandhose/3fe03dd883ba2c5a6132 to your computer and use it in GitHub Desktop.
Stack JS

Titre: Changement complet du stack front

Sous-titre: Tests unitaires, doc automatique, approche par module... La grande classe !

Bonjour à tous, vous le savez peut-être, on (les quelques développeurs front) réfléchit à revoir complètement l'architecture javascript du front. Pour plusieurs raisons :

  • actuellement, il n'y a aucune règle, aucune ligne directice sur comment doit être fait un module
  • on n'a pas de fragmentation claire par module, et les manipulations DOM ( = manipulation dans l'interface) et les requètes AJAX ( = communication avec le serveur) s'entremèlent de manière totalement anarchique
  • il y a actuellement 2 gestionnaires de dépendances/paquets, qui font à peu près la même chose, alors que nous pourrions en supprimer un
  • il n'y a pas de tests unitaires, ni de documentation (en même temps, la structure actuelle ne le permet pas forcément)

[[question]] | Alors, dites-nous tout : qu'est-ce que vous avez prévu de beau ?

La version courte

  • browserify: permet de segmenter correctement le code par module et d'importer (avec require, à la manière de NodeJS et comme la plupart des languages) ces modules
  • React: librairie développée par des développeurs de Facebook, permettant la création d'interfaces
  • JSX: complémentaire à React, sans être obligatoire, permet de simplifier l'écriture de templates pour React
  • npm: déjà présent dans le stack actuel, npm est un gestionnaire de dépendances. Pour les librairies type jQuery, on utilise actuellement bower. Or, avec browserify, l'on peut imaginer utiliser uniquement npm pour toutes les dépendances
  • Karma + Jasmine ou JEST: ce sont des frameworks de tests, qui nous permettront d'écrire des tests unitaires pour le front. Le choix n'a pas encore été réellement fait, sachant qu'il existe encore d'autres alternatives
  • JSDoc: Permet de créer automatiquement de la documentation à partir des commentaires présent dans le code, comme c'est le cas actuellement pour le back. C'est même (à priori) possible de l'intégrer à Sphinx, c'est à dire à la documentation back actuelle o/

La version longue, en détail

Browserify est un module node, développé par substack (<3), permettant d'importer (require) des modules AMD/CommonJS. L'idée, c'est qu'un module va exposer ce qu'il veut dans module.export. Par exemple, la librairie jQuery va exposer l'objet jQuery (ou $) dans module.export.

Ensuite, n'importe où dans les autres fichiers javascript, on va pouvoir importer ce module. Par exemple, si l'on a besoin de jQuery, on va écrire var $ = require("jquery").

L'avantage de ce système, est que l'on peut clairement identifier à n'importe quel endroit de n'importe quel fichier à quoi correspond chaque variable. On a pas de surprise sur d'éventuelles variables globales, déclarées autre part.

De plus, cela simplifie l'écriture de tests unitaires, comme nous l'expliquons plus bas.

Lorsque l'on appelle require, browserify va chercher à plusieurs endroits: si il s'agit d'un chemin relatif (genre ./api/membres), il va chercher le fichier membres.js dans le dossier api/. Si en revanche, il s'agit d'un nom de module, il va chercher dans le dossier node_modules/ qui correspond... aux dépendances npm!

npm est un gestionnaire de dépendances développé, à la base, pour NodeJS (npm = node package manager). browserify va permettre d'accéder à ces modules, et lors de la compilation, tout empaqueter dans un seul fichier, contenant toutes les dépendances nécessaires. Suite à l'apparition de browserify, de nombreuses librairies prévues uniquement pour le navigateur ont été publiée sur npm. C'est le cas nottament de jquery: l'on peut, à l'heure actuelle, installer jquery via npm, avec la commande npm install jquery, et l'importer en écrivant var $ = require("jquery");. Cela évite d'être obligé d'exposer les modules globalement (c'est à dire dans l'objet window), et ainsi éviter tout conflit entre les librairies. jquery, ainsi que d'autres librairies sont actuellement installées via bower. L'utilisation de browserify, couplé avec npm permettra de se débarrasser de bower, qui est actuellement moins stable que npm, et qui a déjà posé problème auparavant.

React (et JSX)

Développée par Facebook, avant d'être mise en open-source, React est une librairie dédiée à la création de composant dans l'inteface, rapide autant dans l'utilisation qu'au niveau performance.

Si vous êtes familier avec l'architecture MVC, React pourrait correspondre au "V" de "MVC" --> abbréviations à mettre

React permet la création d'éléments d'interface, fonctionnants de manière indépendante, réutilisables. Par exemple, l'on peut imaginer un élément <RelativeTime>, auquel l'on va associer une date. En montant (c'est le jargon de React ; signifie "attacher au DOM") cet élément, il va mettre à jour régulièrement l'affichage de la date relative (ex: "Il y a X minutes"). Si un évènement extérieur, par exemple une mise à jour venant du serveur (via l'API), ou un clic sur l'interface par l'utilisateur, vient modifier un attribut d'un élément, celui-ci va automatiquement se mettre à jour en conséquence.

C'est la particularité de React: contrairement à d'autres frameworks front, type Angular ou Ember, le lien entre les objet, entre la vue et le controlleur, (le data-binding) ne va que dans un sens. Dans d'autres librairies, qui optent pour un lien bidirectionnel (two-way databinding), si la vue modifie une propriété (exemple: un champ de texte), elle va directement modifier cet attribut dans le controlleur.

Ce n'est pas le cas de React, qui préfère utiliser Flux. Flux est une partie de la librarie de React, qui s'occupe de la gestion des évènements, quelques soit leurs origines (API, action de l'utilisateur). Ainsi, tous les éléments inscrits à cet évènement en particulier vont changer leur état, et éventuellement modier leur vue.

Ce flux d'évènements évite d'aboutir à des conflits entre les scopes, que l'on peut rencontrer avec Angular

JSX est simplement un "language" qui étend le javascript (qui se compile bien évidemment vers du Javascript), qui simplifie l'écriture de templates avec React.

Par exemple, ce qui s'écrierais en JS de cette manière :

var HelloMessage = React.createClass({
    displayName: "HelloMessage",   
    render: function() {
        return React.createElement("div", null, "Hello ", this.props.name);   
    }
});

React.render(React.createElement(HelloMessage, {name: "John"}), mountNode);

... s'écrit, avec JSX, de cette manière :

var HelloMessage = React.createClass({
    render: function() {
      return <div>Hello {this.props.name}</div>; 
    }
}); 

React.render(<HelloMessage name="John" />, mountNode); 

Bien évidemment, lors de la compilation, le code JSX ci-dessus, va être équivalent au code JS.

Les tests unitaires

Parce que les tests unitaires, c'est le bien, et parce que le back, ils en ont déjà.

Pour ceux qui ne le savent pas, les tests unitaires permettent de tester le code, afin de s'assurer de son fonctionnement. Par exemple, si l'on écrit une fonction d'addition, l'on va la tester en vérifiant que lorsque l'on entre 3 et 5 en paramètres, l'on a bien 8 en retour.

Du fait de l'utilisation de browserify, et de npm, tous le code JS sera, à priori, éxécutable dans node. De ce fait, l'on peut choisir soit d'éxécuter ces tests unitaires dans un navigateur, qu'il soit headless ( = pas d'interface, uniquement dans le terminal, type PhantomJS) ou réel (Chrome, Firefox, IE...), soit éxécuter dans node directement.

La première approche utiliserait donc Karma et une framework de tests, type Jasmine ou Mocha, et lancerait les tests unitaires dans un navigateur. L'autre approche utiliserait JEST, qui est un framework de tests tournant directement dans node, et à priori plus adapté dans notre cas, puisqu'il préconise une utilisation de modules (require), comme ça sera le cas avec browserify.

Typiquement, les tests ressembleraient à cela, avec JEST:

// sum.js
function sum(value1, value2) {
    return value1 + value2;
}
module.exports = sum;
---
// __tests__/sum-test.js
jest.dontMock('../sum'); 
describe('sum', function() { 
    it('adds 1 + 2 to equal 3', function() {
        var sum = require('../sum');
        expect(sum(1, 2)).toBe(3);
    });
});

Avec Karma, on est obligé d'exposer les fonctions/modules à tester globalement, et de les inclure dans tous les tests. Je ne sais même pas si c'est possible avec ce stack-là... A tester, donc

JSDoc permet la génération de documentation à partir des commentaires présent dans le code. L'organisation par module permettra de segmenter clairement et proprement cette documentation. Il est même possible, à l'aide de jsdoc-rst-template de générer des fichiers reStructuredText (.rst), afin de l'intégrer à Sphinx, c'est à dire à la documentation back actuelle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment