Archives pour la catégorie protip

Écrire des scripts npm multi-plateforme

npm c’est très bien, j’ai complètement abandonné gulp, grunt, et consors, et je commence même à embrasser ma condition d’allergique au fichier de conf (le package.json sera mon unique tolérance). Bref, si comme moi votre « task runner » est npm, alors comme moi vous avez du vous heurter au cas des « autres » plateformes, celles qui n’ont pas les mêmes commandes que vous, voire pas de commande du tout pour ce que vous voulez faire… c’est-à-dire Windows et son shell de Néandertal. Voici donc une série de modules node qui résolvent ces questions.

Commandes de base

COPY vs cp, MKDIR vs mkdir -p, etc… les commandes de base ne sont pas acquises du tout, passez par des modules npm faits pour ça :

  • rm -rf filesrimraf files
  • cp -r source targetcpx source target (qui a en plus une option --watch pour maintenir la cible à jour)
  • mkdir -p a/b/cmkdirp a/b/c

Variables d’environnement

La syntaxe ENV_VAR=value commande sous Windows ne fonctionne pas.

  • Utilisez plutôt cross-env ENV_VAR=val command

Exécuter plusieurs commandes

  • Plusieurs scripts npm en parallèle :
    • npm run a & npm run b & npm run c & waitnpm-run-all --parallel a b c (plus court, plus solide, plus universel)
  • Plusieurs scripts npm en série :
    • npm run a && npm run b && npm run c fonctionne très bien, pas besoin d’outil sur ce coup
    • npm-run-all a b c sera plus concis
  • Plusieurs commandes hors scripts npm, en parallèle : aggregate-commands (mais autant mettre ces commandes en script npm et utiliser npm-run-all)

Commandes de « watch »

Aucune excuse !

Vous n’avez maintenant plus aucune excuse pour ne pas écrire de scripts de « build » qui tournent partout, sans pour autant vous encombrer de task-runners obèses. Vous en connaissez d’autres ? Commentez !

Mes 2 patterns autour des promises

TL;DR: Les promesses c’est meilleur avec du sucre fonctionnel.

En réaction à l’article « My five promise patterns », j’avais envie de partager ma façon de faire. En effet si je le rejoins sur une grande partie, je trouve qu’il a oublié d’insister sur des points bien plus essentiels…

Choisir sa librairie, mais rester proche du natif

À part Q (dernier sur tous les benchmarks, sauf quand il y a aussi jQuery) il n’y a pas vraiment de mauvais choix. Personnellement j’utilise souvent Bluebird qui représente pour moi le meilleur rapport fonctionnalités/performances (voire performances tout court). Ceci étant dit, j’ai lancé son benchmark sur ma propre machine et j’ai trouvé des résultats bien différents de ce que l’auteur avance 😉 Je pense donc de plus en plus utiliser when.js.

Moralité : les promesses étant une partie fondamentale (flow control) de votre programme, il ne faut pas se laisser enfermer dans une librairie qui vous priverait de gains de performances significatifs. Donc au final je préfère éviter au maximum d’utiliser les fonctionnalités supplémentaires genre Promise#map() & co.

Lire la suite

Ma boite à outil Node.js

Voilà le genre d’article qui peut servir à tout le monde, et qui peut devenir une formidable opportunité d’échange pour moi si vous venez partager vos propres « batbelt » en commentaire. Donc n’hésitez pas :)

Je travaille au quotidien avec Node.js (à tel point que j’ai presque oublié comment ça marchait côté client ;)), et vous imaginez donc que j’ai des millions d’outils super bien gaulés pour me faciliter la vie au quotidien. Raté ! Il y en a finalement assez peu, et ce sont les grands classiques que vous connaissez déjà probablement. Mais qui sait, si ce n’est pas le cas, ce post pourrait changer un petit bout de votre vie !

Séance bookmarks, c’est parti.

Lire la suite

Le « Monkey Patching », ou l’AOP du pauvre

Le monkey-patch, c’est le fait de pouvoir écraser des attributs, méthodes, etc… au moment de l’exécution. On s’en sert en général à remplacer ou étendre une méthode.

En JavaScript, le monkey-patching est extrêmement simple, puisqu’on peut nativement remplacer n’importe quelle méthode d’un objet par une fonction dynamiquement.

Remplacer une méthode

C’est trivial :

object.method = function () {
  // this === object
  // …
};

Modifier le comportement d’une méthode

Supposons que j’ai la classe « Entity » possédant une méthode « save()« . On a un problème, cette méthode a tendance à enregistrer des données complètement corrompues mais on n’arrive pas à savoir dans quelles conditions ça arrive. Le plus simple serait de pouvoir se « brancher » sur cette méthode pour logger certaines informations afin d’en savoir plus.

Le monkey-patching est une façon simple d’y arriver :

// wrap to avoid global context pollution
(function () {
  // store original method
  var _save = Entity.prototype.save;
  // override method
  Entity.prototype.save = function () {
    log_stack_trace(new Error().stack); // grab a stack trace to know where I've been called from
    log_entity(this); // log entity to check data
    // call original method
    _save.apply(this, arguments);
  };
})();

Lire la suite

Profiler son application NodeJS

Je me suis essayé à un exercice dont je n’ai pas l’habitude: faire du profilage d’applications. Je n’en ai généralement pas eu besoin, les bottlenecks étant souvent faciles à identifier dans les applications sur lesquelles j’ai travaillé, mais viendra tôt ou tard le jour où on se demande si on ne peut pas simplement « faire mieux ». Il n’y a pas de problème particulier, pas d’URL ou de fonction spécifiquement lente identifiée, et dans ce cas si on veut améliorer les performances il faut qu’on trouve déjà où ça pourrait être amélioré 😉

Je pars d’assez loin, ma seule expérience tient dans XDebug et KCachegrind avec PHP. Expérience plutôt concluante d’ailleurs.

Le paysage est beaucoup moins rose du côté de Node.JS, d’une part à cause du peu d’outils « finis » disponibles. Pour résumer, la plupart des outils que j’ai trouvés me semblent plus utiles aux développeurs de V8 qu’au développeur JavaScript… Si vous avez la flemme de lire ce roman, vous pouvez passer directement à la conclusion où vous trouverez un tableau récapitulatif absolument subjectif 😉

Sommaire

Avertissement

Je préviens les pro du profiling qu’il y aura dans cet article de probables énormités sans doute impardonnables. Je vous demande deux choses: aidez-moi à corriger ces énormités :) mais prenez quand-même le temps de vulgariser à destination des débutants (m’incluant) 😉

Lire la suite

Mémo BASH: gestion des process

Ça fait un bail que je n’ai pas posté, je profite de l’écriture d’un mémo interne pour me permettre de le copier-coller ici 😉

Comme ces derniers temps j’ai écrit pas mal de scripts de maintenance Bash, je souhaite partager avec vous mes connaissances sur la gestion des process avec le shell (ce qui est quand-même la principale raison pour laquelle on écrirait du shell, outre la portabilité):

Exécution

$command lance la commande et attend son retour
$command & lance la commande en arrière plan
wait attend la fin de tous les process en arrière plan du process courant (code de retour = 0)
wait $PID attend la fin du process caractérisé par ce PID (code de retour = code de retour du process attendu, s’il y en a plusieurs c’est le dernier)

Signaux

kill -0 $PID échoue si aucun process avec ce PID n’existe
trap $command $signal intercepter le signal et exécuter la command indiquée (idéal pour affecter des commandes de nettoyage en post-execute),
exemple: trap 'echo fin' EXIT INT TERM

Variables spéciales

$$ le PID du process courant
$! le PID du dernier process lancé en arrière plan
$? le code de retour de la dernière commande terminée (dans un trap ça peut être le code de retour du process en cours, très utile)

Redirections

$command 1> $file redirige l’output standard vers un fichier
$command 2> $file redirige l’output erreur vers un fichier
$command 1>&2 tout rediriger vers l’output erreur
$command 2>&1 tout rediriger vers l’output standard
$command &> $file tout rediriger vers un fichier
exec &> $file toutes les commandes exécutées après cet appel verront leurs sorties redirigées vers un fichier (exec est en fait bien plus puissant que ça)

Exemple bidon

#!/bin/bash
(sleep 2 && echo 1 && exit 1) &
PID1=$!
(sleep 4 && echo 2 && exit 2) &
PID2=$!
trap "echo Nettoyage... && kill -9 $PID1 $PID2" INT TERM
trap "echo Terminé (code $?)!" EXIT INT TERM
wait $PID1 $PID2
echo code de retour du sleep: $?

N’hésitez pas à partager vos protips de gros barbu en commentaire \o/