Connecter un frontend SPA Vue.js à une API backend

Temps de lecture ~4 minutes

Vue.js est un excellent framework javascript frontend et sa documentation est très claire et va droit au but. Vous pouvez soit choisir d’intégrer Vue à une application préexistante (à la JQuery) ou construire une Single Page Application (SPA) basée sur Webpack façon React.js. Mettons en place une SPA très simple ici qui appelle une API REST distante en utilisant Node.js, Webpack, Vue Loader, Vue Router, et Axios. La mise en place de ce type de projet n’est pas si évidente que cela selon moi, j’essaye donc ici de faire un petit tuto sur la façon de procéder sur Ubuntu. Pour information, voici pourquoi l’on utilise Webpack.

Mettre en place un projet Vue.js

Installer Node.js et npm.

Puis utiliser npm pour installer vue-cli et utiliser vue-cli pour installer le loader pour Webpack appelé vue-loader qui vous permet d’utiliser les components Vue mixant HTML, CSS, et JS au sein d’un même fichier .vue. Cela installe aussi tout le reste de l’écosystème nécessaire à une SPA comme par exemple vue-router. Enfin, installer Axios que nous utiliserons pour la connexion à l’API.

sudo npm install -g vue-cli
vue init webpack vue_project  # Answer various questions here
cd vue_project
npm install
npm install --save axios

Plus d’informations sur la structure du projet ici.

Workflow

Dev

Le dev est grandement facilité par la présence d’un serveur web local permettant le rechargement à chaud (la page web est actualisée à la volée lorsque vous modifiez votre code). Lancez simplement :

npm run dev

et commencez à coder.

Note : personnellement j’ai rencontré un bug qui m’empêchait d’utiliser la rechargement à chaud à cause d’un problème de permission Linux (je suis sur Ubuntu 17.10). J’ai réglé le problème avec la commande suivante :

echo 100000 | sudo tee /proc/sys/fs/inotify/max_user_watches

Déploiement

Une fois que vous avez besoin de déployer votre app en production, lancez :

npm run build

et votre app est maintenant compilée dans le dossier dist. C’est à vous de décider comment vous souhaitez la déployer sur votre serveur. Personnellement je place mon app dans un conteneur Docker avec Nginx et je fais pointer Nginx vers le dossier contenant mon app grâce au bloc suivant :

location / {
    root /my_app;
}

Bien entendu, si vous avez déjà un autre service tournant sur le port 80 du même serveur, il vous faudra réfléchir à la façon dont vous devez organiser vos services et modifier votre config Nginx en conséquence.

Se connecter à l’API backend

Tout se passe à l’intérieur du dossier src à partir de maintenant.

Paramétrer les noms de serveurs dev et prod une fois pour toutes

Mon serveur de développement API tourne à l’adresse http://127.0.0.1 tandis que mon serveur de production API tourne sur http://api.example.com donc afin d’éviter un changement de ma config à chaque déploiement j’ai créé le fichier http-constants.js suivant à la racine du dossier src :

import axios from 'axios'

let baseURL

if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
  baseURL = 'http://127.0.0.1/'
} else {
  baseURL = 'http://api.example.com'
}

export const HTTP = axios.create(
  {
    baseURL: baseURL
  })

et ensuite dans chaque fichier vue nécessitant Axios, importez HTTP au lieu d’Axios :

import {HTTP} from '../http-constants'

HTTP.get(...).then(...).catch(...)

Note : cette fonctionnalité de proxying devrait en théorie pouvoir se faire plus facilement au sein du fichier de config config/index.js en utilisant la directive proxyTable mais cela n’a pas fonctionné pour moi.

Créer l’app

Créons une app appelée ShowGreetings qui récupère un message Hello World depuis l’API. Le point d’accès de l’API est /greetings et retourne le message JSON suivant lorsque l’on envoie une requête GET :

{message: "Hello World"}

Créez en premier le nouveau component Vue appelé ShowGreetings.vue dans src/components :

<template>
  <div>
    <button @click="getGreetings">Get Greetings</button>
    <h1 v-if="greetings"></h1>
    <p class="error" v-if="errorMessage"></p>
  </div>
</template>

<script>
import {HTTP} from '../http-constants'
export default {
  name: 'ShowGreetings',
  data () {
    return {
      greetings: '',
      errors: ''
    }
  },
  methods: {
    getGreetings: function () {
      HTTP.get('/greetings')
        .then(response => {
          this.greetings = response.data.message
        })
        .catch(e => {
          this.errors = e
        })
    }
  }
}
</script>

<style scoped>
.error {
  color: red;
}
</style>

Ce component essaie de se connecter à l’API backend lorsque vous cliquez sur un bouton et affiche le message en retour. Si une erreur est retournée, on affiche une erreur.

Maintenant mettez à jour le routeur afin de prendre en compte ce nouveau component. Voici notre nouvel index.js dans src/router:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import ShowGreetings from '@/components/ShowGreetings'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/show-greetings',
      name: 'ShowGreetings',
      component: ShowGreetings
    }
  ]
})

On a créé une route appelée “ShowGreetings” de façon à pouvoir appeler la route par son nom plutôt que par son chemin (beaucoup plus flexible).

Enfin, éditez le component App.vue dans src afin qu’un lien vers notre nouveau component apparaisse sur la page d’accueil :

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-link :to="{ name: 'ShowGreetings'}">Show Greetings</router-link>
    <router-view/>
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Ici on s’est contenté d’ajouter un nouveau tag router-link.

Conclusion

Une fois que l’on comprend comment interagissent les différents couches en action, cela devient très facile de construire une SPA avec Vue.js qui passe à l’échelle facilement d’un petit projet à un gros projet en production.

L’intégralité de ce petit projet est disponible sur mon GitHub si besoin.

Also available in English

Rate Limiting d'API avec Traefik, Docker, Go, et la mise en cache

Limiter l'utilisation de l'API en fonction d'une règle avancée de limitation du débit n'est pas si facile. Pour y parvenir derrière l'API NLP Cloud, nous utilisons une combinaison de Docker, Traefik (comme proxy inverse) et la mise en cache locale dans un script Go. Si cela est fait correctement, vous pouvez améliorer considérablement les performances de votre limitation de débit et étrangler correctement les demandes d'API sans sacrifier la vitesse des demandes. Continuer de lire