Node.js & Express: comment packager et partager ses applications

S’il y a bien une chose qui craint avec les technologies « cool » et récentes, c’est la doc. Et Node.JS (ou plutôt la grande majorité de ses modules, car l’API de Node elle-même est plutôt bien documentée) n’échappe pas à la règle, et les contributions de @visionmedia quoi que d’excellentes facture et très populaires, en sont hélas une illustration 😉 Du coup, il y a des fonctionnalités qu’on ne découvre qu’en farfouillant dans le code…

Je refléchissais en ce moment à un moyen de « packager » les applications Express dans Node.JS, de manière à les réutiliser. Naïvement, j’étais persuadé que ça n’était pas possible, et je suis parti dans le développement d’un framework permettant de simplifier ce packaging, avec des vues embarquées, etc… Naïf, oui, car évidemment cette fonctionnalité existe déjà dans Connect (la couche sous Express): quand on appelle app.use(une_autre_app), c’est comme si on « fusionnait » les deux applications. Ce comportement, ainsi que les valeurs de configuration disponibles, étant très mal documentées, je vais vous en parler ici 🙂

Continuer la lecture

Varnish & les Edge Side Includes pour faire du cache partiel de page

ESI – ou Edge Side Includes – est une solution de mise en cache partiel de page. L’idée générale est d’avoir des « portions » de la page qui sont servis avec différentes règles de mise en cache que le reste de la page.

On peut imaginer une page qui sera mise en cache dans sa globalité, sauf le petit widget « panier » qui lui ne sera pas mis en cache. Une problématique extrêmement fréquente et qui empêche généralement toute mise en cache, alors qu’on n’a qu’un tout petit morceau de la page qui est réellement dynamique 🙁
L’idéal serait alors que la page soit mise en cache complètement, et que sa partie dynamique soit simplement identifiée par un « marqueur », et que la navigateur aille chercher le contenu de ce « marqueur » à une autre adresse, qui elle a une politique de mise en cache différente.

Et bien c’est ce que propose ESI 🙂 Le marqueur en question est un tag XML <esi src="adresse du morceau de page à rendre" />. Par contre les navigateurs ne comprennent pas ce langage directement, il faut donc ajouter entre les deux un « proxy cache » qui lui saura interpréter ces portions, et rendre au navigateur le résultat final.

Continuer la lecture

Le point sur Javascript et l’héritage prototypal

Javascript n’est pas à proprement parler un langage objet, mais il dispose quand-même d’un opérateur new et de trucs qui ressemblent vachement à des propriétés et des méthodes. Donc par raccourci, on parle d’objet.

Dans les différents tutoriels sur le sujet, quand on aborde l’héritage, la méthode proposée est souvent celle-là:

1
2
3
4
5
6
7
8
9
10
function Animal(nom) { // class Animal
  this.nom = nom;
}
Animal.prototype.manger = function() { // Animal.manger()
  console.log('Miam!');
}
function Chien(nom) { // class Chien extends Animal
  Animal.call(this, nom); // super(nom)
}
Chien.prototype = new Animal(); // le fameux extends est là

Cette méthode n’est pas parfaite puisque pour implémenter l’héritage on va instancier un objet de la classe parente. WTF ? Du coup, faisons un petit tour des méthodes alternatives.

Continuer la lecture

Nodester: Hébergez vos applis NodeJS

J’ai découvert aujourd’hui Nodester: une plateforme d’hébergement d’application NodeJS. J’ai pu m’inscrire et faire les tous premiers tests, donc je vais vous faire part de mes impressions 🙂
Alors je vous le dis tout de suite: on est très loin des standards d’hébergement du monde PHP auquel je suis plus habitué. Exit le FTP (voire le SSH si on a de la chance), on a une API, avec un outil en ligne de commande, pour s’inscrire, créer, déployer et contrôler ses applications. Avertissement: Si vous testez, faites un peu attention à ce que vous faites, car je n’ai pas trouvé comment on supprimait son compte, ni comment on pouvait supprimer une application initialisée.

Note: J’ai aussi ouvert un compte sur DuoStack, mais je n’ai pas encore pris le temps de tester. On verra ça dans la semaine probablement 😉

Pré-requis

  • node
  • npm
  • une clé SSH (si vous utilisez déjà GitHub, pourquoi ne pas réutiliser celle que vous avez déjà l’habitude d’utiliser pour vos dépôts Git): en effet, le déploiement se fait par git push 😀

Continuer la lecture

« 304 – Not Modified » est votre ami

Spéciale dédicace à Romain (aka Palleas), sans l’obstination de qui tout cela n’aurait pas été rendu possible :’)

J’ai commis un petit plugin WordPress (activé ici-même) qui permet d’optimiser la mise en cache du navigateur et de reposer d’autant le serveur 🙂 Plusieurs ingrédients permettent cette opération, et surtout la rendent intéressante:

  • La fréquence de publication est faible, il y a donc de très fortes chances qu’un visiteur revoit le même contenu à chaque fois qu’il ira sur le blog.
  • Le blog ne s’encombre pas d’éléments dynamiques hors des posts, pages, et commentaires. La « date de dernière modification » globale est donc très facile à déterminer: c’est la plus grande des dates de dernière modification de chacun de ces types d’éléments.

Partant de là ce plugin va donc implémenter correctement ce qu’on oublie trop souvent de faire 🙂 Continuer la lecture

Node.JS: l’avènement de la programmation asynchrone ?

On est plutôt habitué dans nos développements à faire du synchrone: on appelle une fonction, elle retourne une valeur quand elle a fini de travailler. Avec Javascript ça peut être totalement différent, par exemple avec Node.JS:

var fs = require("fs");
fs.readFile("fichier.txt", function(err, content) {
  if (err) {
    console.err(err);
  } else {
    console.log("file read: " + content.length + " bytes");
  }
}
console.log("after readFile");

En programmation synchrone, ce bout de code aurait lu le fichier, affiché « file read: X bytes » puis « after readFile ». Avec Node.JS ce n’est pas le cas, car toutes les fonctions systèmes ont une version synchrone (qui renvoie un résultat et lève une exception en cas d’erreur), et une vesion asynchrone (qui ne va rien renvoyer, rendre tout de suite la main, et prendre en paramètre un callback acceptant une éventuelle exception et le reste des paramètres). Continuer la lecture

Un bug bien classique qui permet de parler de JS et du scope

J’ai pu débugger récemment ce bout de code:

1
2
3
4
5
6
// on a n boutons, cliquer sur le bouton "i" a pour effet de cacher un lien correspondant
for (var i=0; i<nbCheckboxes; i++) {
  $('input[name="val' + i + '"]').click(function() {
    $('#link'+i).hide();
  });
}

Etrangement, quelque soit le bouton cliqué, rien ne se passait… Après vérification, à chaque clic jQuery essayait de me cacher le lien « #link5 » (sachant que j’avais 5 liens, numérotés de 0 à 4, ça pouvait moyennement marcher).

Mine de rien, ce petit bug peut arriver. Rarement, parce qu’on a rarement un code aussi mal foutu hein 🙂 mais ça peut arriver. Et ce petit bug de rien du tout relève d’une feature mal comprise de Javascript que j’appelle les « contextes dynamiques », mais qui relève simplement de la portée des variables. Continuer la lecture