Photo du film Star Wars

On a tous vécu ce bug-surprise qui n’apparait qu’en production. Tout allait bien en local, puis une fois déployé, c’est le drame.

Avoir une maîtrise des environnements (local, pré-production, production) permet d’éviter 99,99%* de ces problèmes (voir la conclusion pour le petit astérisque). En plus de cela, vous allez gagner du temps et votre code sera plus solide et safe.

On fait communément la différence entre l’environnement local (ou développement, en gros: mon ordinateur) et remote (serveur distant de pré-production ou production).

On appelle production la version “live”, c’est celle qui est utilisée par vos utilisateurs et qui tourne en ce moment même. Vous êtes actuellement sur la version de production de Medium.

La pré-production est un environnement à part entière qui peut être sur le même serveur que la production ou non. Il a pour but de réaliser des tests et validations avant le déploiement en production.

Les variables d’environnement

Comme son nom l’indique les variables d’environnement dépendent de l’environnement dans lequel l’application est installée. Examples : l’URL de l’application ou de l’API, les identifiants (base de données, services tiers…), les configurations, etc.

Quel que soit votre techno, les bonnes pratiques nous poussent à réunir toutes ces variables dans un seul et même fichier.

Dotenv (.env) est un design pattern disponible sous forme de module pour quasiment tous les languages. Même le mal-aimé (ou bien-aimé) Wordpress dispose de solutions comme Bedrock qui intègrent dotenv.

Prenons l’example de l’utilisation de dotenv du framework Laravel :

APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

[...]

C’est simple, non ?

Notez que ce fichier s’appelle .env.example et non pas .env car le “vrai” fichier .env est personnel et privé (il ne doit jamais être commité sur git). Chaque développeur est prié de copier ce fichier, de le renommer en .env et de remplir ses propres identifiants. Rien d’autre, tout est là.

Cela permet d’améliorer la sécurité car il n’y pas d’identifiants qui se promènent en dur dans le code. Cette pratique permet aussi de faciliter la collaboration avec d’autres développeurs qui pourront faire tourner rapidement votre app.

En plus des identifiants, on peut aussi réaliser des actions différentes en fonction de l’environnement dans lequel on est.

Dans l’exemple ci-dessous, on récupère l’adresse email d’un vendeur (sales person) pour lui envoyer un email. Dans un environnement local ou de pré-production (staging), l’email ne sera pas envoyé au vrai vendeur mais sur un mail de test (le mien). Pour finir, ce mail de test est également stocké dans une variable d’environnement TEST_EMAIL, ce qui fait que les développeurs avec qui je collabore pourront le recevoir sur leur propre email :

public function getSalesPersonEmail()
{
    if (env('APP_ENV') == 'local' || env('APP_ENV') == 'staging') {
        return env('TEST_EMAIL');
    }
    return $this->sales_person_email;
}

Ce type de code doit être fréquent dans votre application. Cela va vous permettre de pouvoir utiliser l’application en profondeur sans rien changer au code.

Les task runners (Gulp, Webpack, Grunt…)

Si vous utilisez des task runners, différencier les environnements vous apporte des avantages :

  • Rapidité de compilation en ne minimifiant les images et assets qu’en production
  • Sécurité : ne générer des sourcemaps qu’en local
  • Propreté : ne pas polluer votre code de développement avec de l’inline-css ou des scripts de web analytics par exemple

Je vais prendre Gulp comme example mais on peut le faire avec d’autres task runners. Le module gulp-util permet de faire la différence entre

gulp

et

gulp —-production

Une fois téléchargé le module, vous pouvez l’utiliser dans votre gulpfile.js. Le code ci-dessous permet de minimifier (avec uglify) en environnement de production uniquement :

var gulp = require('gulp'),
    // ajouter les autres dépendances ici
    util = require('gulp-util');

// deux points d'exclamation pour changer le undefined en false
var production = !!util.env.production;

// pour le tester vous-même
console.log(production);

gulp.task('scripts', function () {
  return gulp.src([
    // ajouter vos dépendences 
  ])
      .pipe(concat('all.js'))
      .pipe(production ? uglify() : util.noop())
      .pipe(gulp.dest('./dist/js'));
});

La virtualisation

On ne peut pas parler de différences d’environnement sans parler de virtualisation bien entendu. La virtualisation a reproduire un système sur un autre. Example : je développe mon application sous Mac mais mon serveur de production est sous Linux, je vais donc créer une machine virtuelle Linux pour mon développement.

L’objectif est simple : travailler en se rapprochant le plus possible de l’environnement de production.

Si j’utilise Apache (MAMP, WAMP et autres) en local et que mon serveur de production fonctionne avec NGINX, je ne peux pas prévoir les erreurs qui vont se produire après mon déploiement.

J’utilise Vagrant pour résoudre ce problème. Docker est un outil permettant une approche différente qui est de plus en plus adopté par les développeurs.

Attention : la virtualisation ne reproduit en aucun cas les performances d’un serveur de production. Si votre application est gourmande en ressources, il faut le tester dans un environnement similaire.

Est-ce que c’est obligatoire ?

Personnellement j’ai eu l’habitude pendant longtemps de ne pas créer d’environnement virtuel pour les “petits” projets. Ma réponse était la suivante: “Je connais mes serveurs et mon environnement local, il n’y aura pas de problème”. Ce manque de considération m’a parfois joué des tours et m’a forcé à passer beaucoup de temps sur des petites choses. Je recommande donc de le faire pour tous les projets. Gardez en tête qu’une minime différence de version de PHP ou NodeJS peut vous bloquer totalement votre application.

Conclusion

Comme vous avez pu le constater, cet article présente une vision générale et non pas détaillée des problématiques liées au changement d’environnement. Chaque technologie est différente et vous trouverez de très bons articles adaptée à votre cas en cherchant sur internet.

Maîtriser les changements d’environnement apporte de la solidité dans votre code, réduit nettement les possibilités de bugs, améliore la sécurité et la collaboration avec d’autres développeurs.

Tout cela aux prix de quelques lignes de code en plus, qui vous feront gagner bien plus de temps qu’elle n’ont prit à être écrites !

*Pourquoi éviter 99,99% des problèmes et pas 100% ? Pour cela, il faudrait un environnement parfaitement identique lors du développement et de la production, ce qui n’est pas possible dans la pratique. Mais cela relève plus du détail qu’autre chose. Allez, au travail !