Vue.js : Deux applications pour le prix d’une

Cet article est la retranscription écrite du meetup donné à la Malterie le mercredi 3 octobre dernier. Il fait également suite à un précédent article sur notre utilisation de Vue.js chez Malt il y a un an. Le but de celui-ci est d’apporter des précisions sur notre expérience sur Vue.js pendant l’année écoulée.

Ce dont on va parler ici :

  • Construction et consommation de nos API au sein de nos applications
  • Exposition globale de styleguides à tous nos composants
  • Mutualisation de composants entre plusieurs applications
  • Logging/Alerting en production

Ce dont on ne parlera pas (du moins pas dans cet article) :

  • State managment (vuex)
  • Routing (vue-router)
  • Message passing (bus d’événement)
  • Internationalisation
  • Comment réussir sa crème anglaise (tout réside cependant dans le feu doux)

Où en sommes-nous ?

Après une année d’utilisation assez intensive de Vue.js chez Malt il est temps de faire le bilan (calmement). Comme développé dans mon précédent article, nous avons une première application en production : Shake, notre CRM maison (Customer Relationship Managment), utilisé par nos commerciaux au quotidien. Et depuis deux mois, nous avons commencé à construire notre deuxième application, destinée cette fois-ci aux entreprises.

Qui a dit qu’un soft interne ne pouvait pas être beau ?

Le but de cet article n’est pas de revenir sur les raisons qui nous ont poussées à choisir Vue.js comme framework javascript. Je peux cependant avancer sans peine qu’après un an, ces raisons ont toutes été éprouvées et que nous n’avons pas regretté ce choix une seule fois.

Don’t worry be API (ne vous sentez pas obligé de rire à celle-ci)

Premier focus de cet article, il me semblait important de s’attarder sur la manière dont ont été construites les API utilisées sur nos deux applications.

Pour comprendre au mieux ce qui nous a motivé dans ces choix, voilà le cas d’usage que nous voulions éviter :

Partie script d’un composant Vue

On peut noter plusieurs choses :

  • Logique de bas niveau directement dans le composant (API fetch)
  • Reconstruction nécessaire d’une url d’API côté front
  • Manipulation d’id de ressource

L’API de nos applications reposent sur deux principes :

  • REST : Representational State Transfer (manipulations de ressources, au moyen de verbes HTTP tels que GET, POST, PUT, DELETE…)
  • HATEOAS : Hypermedia As The Engine Of Application State

Je ne développerai pas l’aspect REST de nos API qui est assez connu. En revanche, le principe de construction HATEOAS me semble assez inhabituel et intéressant pour vous le présenter plus en détail.

L’idée derrière ce sigle cryptique est que chaque ressource exposée dans l’application est auto-porteuse de tout ce dont on a besoin pour la manipuler.

One link to rule them all

Le seul endpoint dont l’application doit avoir connaissance est celle du registre. Un point d’entrée unique, qui donne accès à un ensemble d’endpoints pouvant être consommées directement :

Le fameux registre, un dictionnaire de liens d’API de base

Les ressources exposées par ces différentes API suivent le même principe et sont également porteuses de leur propre registre:

Un exemple de registre de ressource, avec une ressource “Account”

Les seules données que doit connaître l’application côté front sont donc :

  • Le lien d’entrée vers le registre de base
  • Les clefs correspondant aux API (du registre de base ou de chaque ressource)

Plusieurs points de douleurs évoqués dans l’exemple de composant Vue ci-dessus sont donc résolus :

  • Très faible dépendance entre construction de l’API côté back et consommation de celle-ci côté front : si un refacto intervient sur les urls d’API, il n’y aucune modification à prévoir côté front, les clefs associées n’ayant subies aucun changement.
  • Aucune connaissance de l’API à avoir côté front. L’application n’a jamais à manipuler ou reconstruire directement des urls d’API.
  • Aucune manipulation direct d’id de ressource

Let’s be Class

Après avoir décorrélé au maximum construction de nos API et consommation de celles-ci restait un dernier souci : ne pas exposer de logique applicative de bas niveau au sein de nos composants (l’utilisation directe de l’API fetch dans l’exemple précédent).

Pour y remédier, nous avons fait le choix d’associer à chaque ressource exposée par l’API une ressource côté front. L’apport de la syntaxe de classe par ES6 nous y a beaucoup aidés (la transpilation ES6 -> ES5 étant disponible par défaut lors du setup d’une application Vue.js).

Une classe AccountResource
Une simple fonction permet de générer nos ressources côté front

A noter que la classe AbstractResource, dont hérite toutes nos classes javascript de ressource permet de mutualiser plusieurs choses, notamment :

  • un client http maison
  • transformations communes à toutes nos ressources (notamment sur leur registry)

On va finir par parler de Vue.js à un moment ?

On y vient :) Notre dernier point de douleur évoqué dans le premier exemple étant maintenant réglé, regardons à quoi ressemble un composant Vue simple associé à notre ressource Account.

Une carte Account

La partie logique de notre AccountCard.vue contient simplement :

10 lignes : less is more.

Ne nous mentons pas non plus, l’exemple ci-dessus a été volontairement simplifié au maximum pour illustrer l’avantage apporté par nos classes javascript. Il est bien entendu possible que ce composant soit responsable d’autre chose (trigger d’événements, propriétés calculées…).

La partie template de notre composant, elle, est également simple :


Voilà ce que nous a apporté cette manière de construire et de consommer nos API :

  • Plus de connaissance nécessaire de l’API côté front
  • Plus de manipulations directes d’id de ressource
  • Nos composants n’utilisent plus que des méthodes métiers sans avoir à être responsables de la logique applicative de bas niveau
  • Création de classes javascript encapsulant toute la logique de chaque ressource et permettant une mutualisation de cette logique entre plusieurs composants (ex: AccountCard.vue et AccountPage.vue)

Sharing is caring

Comme dit plus haut, l’une des problématiques auxquelles nous avons dû faire face en développant une première puis une deuxième application Vue.js chez Malt a été le partage de ressources (styles, composants, logique…) entre lesdites applications.

J’aime trop ton style

Nous avions déjà réglé le souci d’exposition de nos styleguides sass (variables, mixins, fonctions) au sein de tous nos composants lors du développement de Shake :

L’utilisation du package npm sass-resources-loader et sa configuration au sein du build webpack de Shake nous permettait d’exposer nos outils sass au sein de tous nos composants.

Nous avons aujourd’hui plus de 300 composants Vue et le fait de ne pas à avoir à importer ces outils pour styliser nos composants est un confort non négligeable.

Démarrer plus vite

Lorsque nous avons démarré notre deuxième application - dont un MVP (Minimum Viable Product) est prévu pour la fin de cette année - nous avons souhaité gagner du temps et réexploiter au maximum ce qui avait été fait sur Shake. Nous voulions donc :

  • Mutualiser les composants communs à toute interface graphique (boutons, formulaires, panels, grilles…) ainsi que la logique liée au modèle des nos API (AbstractResource, client http…)
  • Permettre à chaque application de customiser le style par défaut de ces composants

La solution choisie est des plus simples : la création d’un package npm local.

Il suffisait pour ce faire de créer un nouveau dossier, extérieur à nos applications et de le déclarer en tant que dépendance dans ces dernières.

Ajout de la dépendance locale dans le package.json de chaque application

L’étape suivante, en toute logique, a été de “sortir” le plus possible de composants de Shake pour les placer dans ce package vuejs-starter afin de pouvoir les exploiter également dans notre deuxième application.

Import et déclaration des composants communs au sein des applications

Tous nos composants communs étant maintenant dans un package à part et utilisable par n applications, il nous fallait trouver un moyen de customiser la charte graphique de ces composants.

En effet, si Shake est une application interne à destination de nos commerciaux, avec une charte très colorée, ronde et ludique, la deuxième application en développement, elle, adoptera un look’n feel plus formel.

Pour schématiser, nous voulions pouvoir être capables de ça…

… et nous avions déjà la solution :)

En effet, nous avions mis en place la mécanique nécessaire à l’exposition de nos variables, mixins et fonctions sass dans tous nos composants.

Il suffisait de rendre chaque application capable d’overwriter ces styleguides de base. Dans les faits, cela revient à exposer dans tous les composants de l’application :

  • variables, mixins, fonctions de notre package npm vuejs-starter
  • variables, mixins, fonctions propres à l’application courante

La seule contrainte étant un nommage persistant entre package local et applications pour que les valeurs (des variables par exemple) soient bien overwritées.

La guerre des boutons

Par exemple, le style de base de notre composant Btn est le suivant, se basant pour la couleur sur la variable sass $color-primary.

Dans le cadre d’une application en particulier, cette variable de couleur peut être overwritée par des fichiers sass spécifiques à sa charte, tout en prenant bien garde de conserver le même nommage :

A noter que l’exemple ci-dessus est volontairement simpliste et ne concerne que la couleur primaire. Cependant, en faisant l’effort (et nous l’avons fait) de sortir l’ensemble des valeurs définissant son apparence (font size, font family, radius…) dans des variables sass, nous avons rendu possible sa totale customisation au sein de chaque application voulant l’utiliser.


En résumé, pour répondre au besoin de mutualisation de nos composants fondamentaux, nous avons :

  • créé un package npm local contenant ces composants
  • exposé globalement l’ensemble des variables définissant leur apparence
  • laissé la possibilité à chaque application d’exposer en plus ses propres variables afin d’overwriter le style par défaut de ces composants.

Alerte générale

Nous voilà arrivés au dernier focus que je voulais faire dans cet article : l’alerting en production et comment nous l’avons intégré à nos applications.

Pour ce faire nous avons utilisé un outil Saas d’alerting que nous avions déjà branché sur la partie back de Malt : Sentry.

Son intégration côté front et plus particulièrement sur la partie Vue.js de nos applications a été largement facilitée par :

  • un SDK javascript disponible sur npm : raven-js
  • un plugin Vue.js intégré à ce SDK
Initialisation simple de Sentry

La seule donnée dont a besoin le SDK javascript est un DSN (token d’identification) propre à votre compte Sentry.

Côté fonctionnalité d’alerting, on retrouve la plupart des features proposées par ce genre de service :

  • méthode concernée par l’erreur
  • localisation dans les assets javascript
  • user agent de l’utilisateur qui a rencontré l’erreur
  • possibilité d’ajouter des tags (ex: informations sur le user) au log
Stacktrace résumée de l’erreur
Informations relatives au user

Sentry propose deux autres fonctionnalités qui nous ont particulièrement séduits.

Par où es-tu passé ?

Le breadcrumb du parcours utilisateurs jusqu’à ce que l’erreur ait été levée est particulièrement intéressant pour mieux la comprendre et la reproduire.

Sentry et Vue.js

Enfin, l’intérêt majeur du plugin Vue.js de Sentry est un aperçu du composant Vue où a eu lieu l’erreur ainsi que son état (props, data…) au moment de cette dernière.

Un luxe non négligeable pour débuger un composant

La fiche de lecture qui va bien

Pour résumer, au sein de cet article, nous avons passé en revue :

  • La construction et la consommation d’une API HATEOAS
  • La séparation des composants Vue de toute logique applicative
  • L’exposition de styles à un ensemble de composants Vue
  • Le partage de composants entre plusieurs applications Vue.js
  • L’intégration d’un outil d’alerting à une application Vue.js

Et maintenant ?

Un an et deux applications plus tard, nous sommes toujours totalement satisfaits du choix de framework que nous avons fait.

Les quelques points de friction restants devraient être en partie couverts par la version 3 de Vue.js qui arrivera courant 2019. Pour les plus intéressés par ce qui figurera dans cette update majeure, je vous laisse lire l’article alléchant d’Evan You à ce sujet.

Dans mon précédent article, j’évoquais le fait d’utiliser Vue.js sur la partie connectée de Malt :

Cependant, si dans un futur proche nous devions refaire la partie compte utilisateur de Malt et que la question du choix d’un framework se pose, notre argumentaire est déjà solide :)

Ce portage en Vue.js a déjà commencé puisque nous avons refait il y a peu la page missions de Malt, en ayant l’occasion de réinvestir tout ce que nous avions appris dans le cadre de Shake, notre première application :

Une application Vue.js dédiée à notre page “missions”

Et comme nous n’avons pas décidé de nous arrêter là et qu’il faut être nombreux pour révolutionner le monde du travail, sachez que Malt recrute toujours, ça se passe ici !