Déployer une application Vue.js sur Heroku

Heroku reste un moyen vraiment facile, rapide, et surtout gratuit pour déployer une application node.js. On peut alors se poser la question : puisque l’on développe nos applications Vue en se servant dans la plupart des cas d’outils node.js, et que Heroku peut nous fournir un environnement node opérationnel en deux lignes de commande, pourquoi ne pas essayer d’automatiser le déploiement d’une application Vue sur Heroku ?

Et bien c’est tout à fait faisable avec une grande simplicité si l’on associe l’utilitaire vue-cli, l’utilitaire de commande heroku-cli, et un micro serveur Express que l’on intègre à la racine du projet. Sans oublier git bien entendu pour pousser l’application vers Heroku.

Pour suivre ce tuto, vous devez avoir une installation locale node.js fonctionnelle avec NPM, avoir git installé et fonctionnel, et disposer d’un compte avec un email et un mot de passe sur Heroku. Pour ce que nous avons à faire, un compte gratuit suffit et il n’est pas nécessaire que le compte soit vérifié avec une carte de paiement.

Si ce n’est pas déjà fait, commencez par installer vue-cli :

$ npm install -g vue-cli

Et toujours si ce n’est pas déjà fait, installez l’utilitaire Heroku selon la procédure prévue pour votre OS que vous pourrez suivre sur la documentation Heroku. Vous devrez alors le lancer pour y entrer vos données d’authentification Heroku :

$ heroku login Enter your Heroku credentials.
Email: ...
Password: ...

Nous allons créer une micro application de démonstration qui affichera le contenu d’une input box. Pour cela, selon la procédure habituelle avec vue-cli, on choisit le template webpack pour créer l’application demoapp :

$ vue init webpack demoapp
Project name : demoapp
Project description : A Vue.js project
Author : me@domain.tld
Vue build : runtime
Install vue-router? No
Use ESLint to lint your code? Yes
Pick an ESLint preset : Standard
Setup unit tests with Karma + Mocha? No
Setup e2e tests with Nightwatch? No
vue-cli · Generated demoapp.

Vous pourrez choisir le build runtime only, on n’installera pas vue-router (pour cette fois !), on peut accepter le lint et on répondra non pour les tests unitaires et end-to-end. Puis on descend dans le répertoire du projet, on installe les dépendances et on lance le serveur de dev, comme d’habitude :

$ cd demoapp/
$ npm install
$ npm run dev

on obtient alors, sur localhost:8080, l’application générée :

Welcome-Vue

On va la modifier, pour obtenir le comportement désiré. On va utiliser un composant msgBox, qui va communiquer avec le composant supérieur Hello par évènements afin de voir si ce comportement sera toujours valide lorsque l’on sera sur Heroku. On va pour l’instant mettre cela en place et tester en local, comme dans un développement webpack classique. Créons un nouveau composant dans src/components, que nous appellerons msgBox.vue :

<template>
  <div class="wrap">
    <input type="text"
           v-model="msg"
           placeholder="Entrez un message ici ..."
           keyup.enter="changed" />
    <input type="button" value="OK" @click="changed" />
    <input type="button" value="Reset" @click="reset" />
  </div>
</template>

<script>
  export default {
    name: 'MsgBox',
    data () {
      return {
        msg: ''
      }
    },
    methods: {
      changed () {
        this.$emit('changed', this.msg)
      },
      reset () {
        this.msg = ''
        this.changed()
      }
    }
  }
</script>

<style scoped>
  .wrap {
    text-align: center;
    margin-top: 3em;
  }
  .wrap input[type="text"] {
    width: 50%;
  }
  .wrap input[type="button"] {
    width: 10%;
    margin-left: 1em;
  }
</style>

Comme ce n’est pas le but de ce tuto, nous ne détaillerons pas tout cela, mais expliquerons juste de manière globale : nous avons créé un composant qui affiche une input box, un bouton « OK » et un bouton « Reset ». Lorsque l’on tape la touche Entrée dans l’input box ou que l’on clique sur le bouton OK, on envoie un message changed aux composants parents, avec le contenu du champ. Lorsque l’on clique sur Reset, on vide l’input box et on envoie le message changed avec une chaine vide. On a aussi ajouté quelques règles CSS pour rendre tout cela présentable.

Modifions maintenant le composant installé par défaut src/components/Hello.vue pour utiliser notre nouveau composant, comme ceci :

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <msg-box @changed="updateMsg"></msg-box>
  </div>
</template>

<script>
  import MsgBox from './msgBox'
  export default {
    name: 'Hello',
    components: { msgBox },
    data () {
      return {
        msg: 'Bienvenue sur Heroku !!!'
      }
    },
    methods: {
      updateMsg (value) {
        this.msg = value ? value : 'Bienvenue sur Heroku !!!'
      }
    }
  }
</script>

Concrètement, on importe le composant msgBox, on l’insère en écoutant l’évènement changed, et quand celui-ci a lieu, on met à jour le message affiché si la valeur est non-vide, ou on affiche le message par défaut si la valeur est vide. Testons sur localhost:8080 notre micro-application :

Welcome-Heroku

Si l’on entre un texte dans le champ, quand on tape Entrée ou que l’on clique OK, le titre se modifie et quand on clique sur Reset, on revient au titre par défaut. C’est une application très basique, mais qui illustre bien les mécanismes de Vue.js.

Arrêtons maintenant notre serveur de dev (CTRL + C dans le terminal qui a servi à le lancer) et créons un dépôt git avec ce que nous venons de faire, et faisons un commit initial :

$ git init
$ git add .
$ git commit -m "initial commit"

Pour pouvoir utiliser notre application sur Heroku, nous devons d’abord indiquer, dans le fichier package.json comment construire l’application et comment la démarrer. Ouvrez pour cela package.json, modifiez la ligne "start": "node build/dev-server.js", en "start": "node server.js",, et insérez juste au dessous la ligne "postinstall": "npm run build", (n’oubliez pas les virgules). Cela va donner à Heroku les instructions nécessaires pour démarrer l’application et la construire. Le résultat doit donner ceci (c’est juste une partie du fichier) :

"scripts": {
  "dev": "node build/dev-server.js",
  "start": "node server.js",
  "postinstall": "npm run build",
  "build": "node build/build.js",
  "lint": "eslint --ext .js,.vue src"
},

Nous invoquons par contre un fichier server.js à la racine de notre application qui n’existe pas. Nous allons le créer, il s’agira d’un serveur Express minimaliste qui va servir les fichiers créés par le build dans le répertoire dist. Créons donc un fichier server.js à la racine du projet avec ceci dedans :

var express = require('express')
var path = require('path')
var serveStatic = require('serve-static')

var app = express()
app.use(serveStatic(path.join(__dirname, 'dist')))
var port = process.env.PORT || 5000

app.listen(port)
console.log('server started on port ' + port)

Toutes les dépendances sont déjà présentes si vous avez utilisé le template webpack de vue-cli. Le port est fixé à 5000 si la variable d’environnement PORT n’est pas définie, ce qui nous permettra de lancer le serveur sur le port 5000 en local (heroku local), ou sur le classique port 80 lorsque nous serons sur Heroku. Faisons un nouveau commit git pour tenir compte de toutes ces modifications :

$ git add .
$ git commit -m "ajout serveur"

On peut alors déclarer l’application sur Heroku, à l’aide de son utilitaire en ligne de commande :

$ heroku create
Creating app... done, protected-brook-46056

Le nom que vous obtiendrez ne sera bien évidemment pas le même. Lorsque l’on va pousser l’appli sur Heroku, la commande postinstall va la construire. Mais comme webpack utilise pour le build des dépendances qui sont enregistrées par NPM en Dev Dependencies, nous allons, plutôt que de tout changer dans le package.json, déclarer au NPM d’Heroku de se mettre en mode de développement :

$ heroku config:set NPM_CONFIG_PRODUCTION=false

Il ne nous reste plus alors qu’à envoyer le projet sur Heroku, avec un bon push, puisqu’un dépôt distant heroku a été automatiquement ajouté lors du heroku create :

$ git push heroku master

Heroku va répondre avec un assez long log, expliquant tout ce qu’il fait, jusqu’à un dernier « Verifying deploy… done. ». Vous pouvez alors entrer heroku open, qui va ouvrir votre navigateur sur l’URL associée à notre application sur Heroku, dans mon cas https://protected-brook-46056.herokuapp.com/ (vous pouvez y aller, elle est toujours active). Dans votre cas ce sera une autre URL, et normalement, vous pouvez y vérifier qu’elle fonctionne :

heroku-finished

Vous pouvez dès à présent faire toutes les modifications et ajouts que vous voulez à l’application en local, chaque fois que vous commiterez et ferez un git push heroku master, votre application sur heroku se mettra à jour. Vous pouvez aussi jouer avec les branches, etc, comme pour n’importe quel distant git, et vous pouvez aussi ajouter un autre distant sur github par exemple, tout cela fonctionnera.

Voilà, j’espère que ce petit article vous aura aidé. Si vous avez des remarques ou des questions, n’hésitez pas à commenter ou à m’envoyer un message.

A bientôt !