💡
|
Vous êtes en train de lire l’Annexe A du livre “Node.js”, écrit par Thomas Parisot et publié aux Éditions Eyrolles. L’ouvrage vous plaît ? Achetez-le sur Amazon.fr ou en librairie. Donnez quelques euros pour contribuer à sa gratuité en ligne. |
Cette annexe est une sélection de modules npm
(npmjs.com)
à laquelle vous référer pour démarrer rapidement, mais aussi pour découvrir
des usages et des domaines d’application insoupçonnés.
J’ai bâti cette liste à partir de mon expérience personnelle et sur la confiance que je porte aux personnes à l’origine de ces modules.
💬
|
Remarque Versions de Node et npm
Le contenu de ce chapitre utilise les versions Node v10 et npm v6. Ce sont les versions stables recommandées en 2022. |
💡
|
Pratique Jouer avec les exemples dans un terminal
Les exemples titrés d’un nom de fichier peuvent être installés sur votre ordinateur. Exécutez-les dans un terminal et amusez-vous à les modifier en parallèle de votre lecture pour voir ce qui change. Installation des exemples via le module npm
nodebook npm install --global nodebook nodebook install appendix-a cd $(nodebook dir appendix-a) La commande suivante devrait afficher un résultat qui confirme que vous êtes au bon endroit : node hello.js Suivez à nouveau les instructions d’installation pour rétablir les exemples dans leur état initial. |
1. Boîte à outils du quotidien
Ces modules répondent à des besoins quotidiens, pour travailler plus rapidement sur des structures ECMAScript.
1.1. lodash
lodash (npmjs.com/lodash) est une collection de plusieurs dizaines de fonctions pour travailler plus facilement avec des chaînes de caractères, des tableaux, des fonctions et des objets.
Vous pourrez ainsi filtrer, sélectionner, fusionner, vérifier et composer de nouvelles variables, aussi bien pour Node que dans les navigateurs.
'use strict';
const { intersection, first } = require('lodash');
const DC = ['Batman', 'Brainiac', 'Thor'];
const Marvel = ['Spiderman', 'Thor'];
const result = first(intersection(DC, Marvel));
console.log(result); // (1)
-
Affiche
Thor
.
1.2. he
he (npmjs.com/he) est un utilitaire pour encoder et décoder des entités HTML dans des chaînes de caractères.
'use strict';
const {encode} = require('he');
const html = '<h1>Blog Post</h1>';
console.log(html); // (1)
console.log(encode(html)); // (2)
-
Affiche
<h1>Blog Post</h1>
. -
Affiche
<h1>Blog Post</h1>
.
1.3. chance
chance (npmjs.com/chance) crée des données de manière aléatoire. Le module retourne aussi des prénoms fictifs, mais aussi des numéros de téléphone, des nombres, des paragraphes, des dates d’anniversaire, des identifiants Android ou Apple, etc.
Il s’utilise surtout pour générer des données factices à des fins de tests, en attendant les vraies données.
1.4. date-fns
date-fns (npmjs.com/date-fns) est une collection de fonctions
pour travailler avec des dates, plus facilement qu’avec l’objet natif Date
.
Vous pouvez formater, ajouter ou retirer des jours, vérifier si deux périodes de temps se chevauchent ou si deux dates font partie d’une même semaine calendaire.
1.5. tcomb
tcomb (npmjs.com/tcomb) renforce la création de structures typées et non mutables. Cela réduit les effets de bord de nos applications lorsque les données n’ont pas la structure attendue.
'use strict';
const t = require('tcomb');
const GPS = t.struct({ // (1)
lat: t.Number,
lon: t.Number,
}, {strict: true});
const Bordeaux = GPS({ lat: 44.8638, lon: -0.6561 });
const Crest = GPS({ lat: 44.7311, long: 4.9861 }); // (2)
const Toulouse = GPS({ lat: 43.6008, lon: 'r0s3' }); // (3)
-
Définition d’une structure stricte qui a pour propriétés
lat
etlon
, pour latitude et longitude. -
Cet appel va lancer une exception car la propriété
long
est inconnue. -
Cet appel va lancer une exception car la propriété
lon
doit être un nombre.
1.6. eventemitter3
eventemitter3 (npmjs.com/eventemitter3) sert à gérer des événements de manière uniforme dans un script Node et dans les navigateurs.
'use strict';
const EventEmitter = require('eventemitter3');
const emitter = new EventEmitter();
emitter.on('ping', data => console.log('on: %s', data));
emitter.once('ping', data => console.log('once: %s', data));
console.log(emitter.listeners('ping')); // (1)
emitter.emit('ping', ['ping', 'ping']); // (2)
emitter.emit('ping', ['pong']); // (3)
emitter.removeListener('ping');
emitter.emit('ping', ['pong']); // (4)
-
Affiche
[ [Function], [Function] ]
. -
Affiche
on: ping,ping
puisonce: ping,ping
. -
Affiche
on: ping,ping
. -
N’affiche rien, l’événement étant désormais déconnecté.
2. Pendant le développement
2.1. debug
debug (npmjs.com/debug) rend optionnel l’affichage de messages de débogage. Les messages s’affichent en présence d’une variable d’environnement. Nous pouvons ainsi lancer un processus et retracer un cheminement complexe de données.
Par défaut, les messages ne s’affichent pas :
node examples/debug.js
Les messages du débogueur app
s’affichent désormais :
DEBUG=app node examples/debug.js app fromages [ 'livarot', 'chaource' ] +0ms
Nous pouvons en afficher plusieurs en même temps, en usant du caractère *
ou en séparant les noms de débogueurs avec des virgules :
DEBUG=app* node examples/debug.js app fromages [ 'livarot', 'chaource' ] +0ms app:timer now 1531304027271 +0ms
'use strict';
const debug = require('debug');
const log = debug('app'); // (1)
const logInterval = debug('app:timer'); // (2)
log('fromages %o', ['livarot', 'chaource']); // (3)
setTimeout(() => {
logInterval('now %d', Date.now()); // (4)
}, 1000);
-
Création du débogueur
app
. -
Création du débogueur
app:timer
. -
La fonction de débogage s’utilise de la même manière que
console.log
. -
Cette fonction fait appel au débogueur
app:timer
.
2.2. nodemon
nodemon (npmjs.com/nodemon) relance le processus actif dès qu’un fichier ECMAScript ou JSON est modifié. C’est un module exécutable particulièrement utile lorsque nous voulons prendre en compte les changements dans une application qui tourne en continu. C’est le cas des applications web, entre autres.
💬
|
Pour en savoir plus, rendez-vous à la section “Pendant le développement : relancer le serveur automatiquement” du chapitre 7. |
2.3. npm-run-all
npm-run-all (npmjs.com/npm-run-all) est mon outil favori
pour composer avec les scripts npm
.
Il a l’avantage d’être adaptable, de régler finement ce qui
doit être exécuté en parallèle ou séquentiellement.
Le module transfère les arguments aux sous-scripts.
{
"...": "...",
"scripts": {
"build": "npm-run-all -p 'build:*' -s start",
"build:css": "sass ...",
"build:js": "browserify ...",
"start": "node server.js"
}
}
2.4. husky
husky (npmjs.com/husky) intègre Git aux
scripts npm
.
Autrement dit, vous pouvez déclencher des scripts lors d’événements Git,
lors d’un push
, avant un commit
ou après avoir rapatrié des changements.
{
"...": "...",
"scripts": {
"precommit": "lint-staged",
"post-merge": "npm install"
}
}
La liste complète des hooks Git se trouve dans la documentation officielle : git-scm.com/docs/githooks.
2.5. onchange
onchange (npmjs.com/onchange) observe une liste de fichiers en continu et déclenche une commande dès que l’un d’entre eux est modifié. C’est particulièrement utile pour reconstruire automatiquement des fichiers de configuration ou des fichiers front-end pendant le développement.
{
"...": "...",
"scripts": {
"build:css": "sass ...",
"dev": "npm-run-script -p 'watch:*' start",
"watch:css": "onchange '**/*.scss' -- npm run build:css",
"start": "node server.js"
}
}
2.6. tiny-lr
tiny-lr (npmjs.com/tiny-lr) est une implémentation minimale du protocole livereload (livereload.com). Il s’intègre à un serveur HTTP ou à une application Express pour relayer la liste des fichiers modifiés côté client.
Le script ou l’extension navigateur client remplace les anciens fichiers par les nouveaux pour refléter les changements sans recharger la page.
2.7. livereactload
livereactload (npmjs.com/livereactload) recherche les composants React à chaud, c’est-à-dire sans rafraîchir la page ni perdre l’état des données. C’est un module indispensable pour développer des applications front-end réactives.
💬
|
Rendez-vous dans la section “Changements en temps réel dans le navigateur” du chapitre 9 pour en savoir plus sur son installation et son intégration. |
3. Protéger nos applications
Le code que nous écrivons se protège dès la conception et dans le temps. Certains modules filtrent les tentatives d’exploitation de nos applications, tandis que d’autres vérifient si le code déployé est toujours sûr.
3.1. sanitize-filename
sanitize-filename (npmjs.com/sanitize-filename) nettoie une variable de tout caractère ambigu ou qui ne serait pas attendu.
'use strict';
const sanitize = require('sanitize-filename');
console.log(sanitize('aucun-problème.txt')); // (1)
console.log(sanitize('../../.ssh/id_rsa')); // (2)
-
Affiche
aucun-problème.txt
. -
Affiche
.....sshid_rsa
– les caractères/
sont nettoyés car il permettrait de créer des chemins compromettants pour l’application ou le système d’exploitation.
3.2. helmet
helmet (npmjs.com/helmet) est un module à intégrer systématiquement dans toute application Express. Il ajoute des en-têtes HTTP Content-Security Policy, Strict Transport Policy et d’autres qui empêchent le détournement d’informations.
Chacune de ses protections se configure aussi au cas par cas. Elles s’intègrent manuellement dans d’autres types d’applications web, y compris un serveur HTTP natif à Node.
3.3. dompurify
dompurify (npmjs.com/dompurify) nettoie un contenu HTML pour le rendre affichable en toute sécurité. Il nettoie des scripts indésirés, des balises mal formées qui casseraient l’affichage, ou encore des iframes qui injecteraient des contenus tiers sans notre consentement.
3.4. filenamify
filenamify (npmjs.com/filenamify) nettoie une valeur pour retirer tout caractère invalide dans un nom de fichier. C’est pratique pour laisser la possibilité à un utilisateur de choisir un nom de fichier sans pour autant mettre en danger le système ou l’application.
3.5. retire.js
retire.js (npmjs.com/retire) sert à scanner soi-même des
vulnérabilités connues dans des fichiers JavaScript.
Il est complémentaire de la commande npm audit
car il inspecte des dépendances qui ne sont pas forcément sur npm
.
3.6. snyk
snyk (npmjs.com/snyk) est à la fois un service en ligne et un module pour vérifier la présence de failles de sécurité connues dans les dépendances de nos projets.
4. Vérifier la syntaxe de notre code
La vérification syntaxique est un mécanisme s’assurant que votre code respecte la grammaire du langage associé. Elle révèle aussi des anomalies fondamentales (balise mal fermée, expression inconnue, etc.) et renforce des pratiques de programmation commune au groupe de développement.
Vérifier la syntaxe de notre code est une excellente première étape avant d’introduire des tests unitaires ou fonctionnels.
4.1. htmlhint
htmlhint (npmjs.com/htmlhint) vérifie la structure de
nos documents HTML.
Il rapporte les doublons d’attributs id
, la présence de balises
mal formées, l’absence de balise fermante ou encore l’existence de chaînes de
caractères non imprimables dans des attributs critiques, entre autres.
Prenons en exemple le document suivant :
<html>
<head>
<link rel="stylesheet" href="sample.css">
</head>
<body>
<button id="btn" class="btn btn-primary">OK</button>
<button id="btn" class="btn">KO</button>
<BUTTON class='btn__primary--curent btn--active'></BUTTON>
</body>
</html>
Une lecture distraite pourrait nous faire passer à côté d’erreurs et d’incohérences de programmation. Les erreurs de ce genre passent d’autant plus inaperçues que la base de code devient volumineuse et change fréquemment.
L’exécution de htmlhint avec ses règles par défaut remontera les alertes suivantes :
../node_modules/.bin/htmlhint sample.html sample.html: line 1, col 1: Doctype must be first. line 8, col 10: Id redefinition of [ btn ]. line 10, col 3: Tagname [ BUTTON ] must be lower case. ... line 10, col 52: Tagname [ BUTTON ] must be lower case.
4.2. eslint
eslint (npmjs.com/eslint) est l’outil de vérification syntaxique pour ECMAScript par excellence. Il est souple, rapide à mettre en œuvre et s’adapte à des contextes complexes. J’aime son mécanisme de configuration de règles : utilisation systématique du mode strict, nombre maximum de paramètres de fonctions, objets non déclarés, variables inconnues, etc.
eslint expose également des fonctions pour créer vos propres règles métier.
{
"...": "...",
"eslintConfig": {
"env": {
"node": true,
"es6": true
},
"extends": [
"eslint:recommended"
],
"rules": {
"strict": ["error", "global"],
"quotes": ["error", "single"],
"no-undef": "error",
"curly": "error",
"eqeqeq": "error"
}
}
}
Le niveau de sévérité de chaque règle est représenté par un identifiant :
-
none
: règle désactivée ; -
warn
: affiche un avertissement ; -
error
: affiche une erreur (le processus se terminera avec un code d’erreur).
Certaines règles demandent ou acceptent des arguments supplémentaires. Elles sont toutes documentées sur le site web du projet : eslint.org/docs/rules/.
💬
|
Documentation Règles personnalisées
Un exemple réutilisable de règles personnalisées se trouve sur le dépôt GitHub de Airbnb : |
4.3. csslint
csslint (npmjs.com/csslint) est un outil de vérification syntaxique de feuilles de style CSS. Il a été créé par deux anciens ingénieurs de Yahoo! dont les anciens travaux dans le domaine de la performance ont influencé l’architecture et le choix des règles par défaut.
csslint fournit les mécanismes de vérification adéquats pour alerter de
possibles effets de bord de box model, de déclaration incompatible de
@font-face
, de vendor prefix dépréciés ou encore de combinaisons de
propriétés connues pour casser l’affichage dans certains navigateurs.
Prenons par exemple le fichier CSS suivant :
.btn {
background: white;
color: black;
border: 0px solid black;
height: 20px;
padding: 10px;
}
.btn__primary {
background-color: blue;
color: white;
font-size: 1.3em;
transition: font-weight 0.2s ease;
}
.btn__primary--current {
color: gray;
}
.btn__primary--current.btn--active {
font-weight: 700;
}
csslint lancera trois alertes en lisant le fichier sample.css
,
même si celui-ci est syntaxiquement parfaitement valide :
../node_modules/.bin/csslint sample.css csslint: There are 3 problems in sample.css. sample.css 1: warning at line 4, col 11 Values of 0 shouldn't have units specified. border: 0px solid black; sample.css 2: warning at line 4, col 3 Using height with border can sometimes make elements larger than you expect. border: 0px solid black; ...
4.4. doiuse
doiuse (npmjs.com/doiuse) est un utilitaire qui repose sur la base de données du site communautaire caniuse.com. Il nous alerte des possibles incompatibilités de syntaxe en fonction de la liste de navigateurs à gérer. Cette liste concerne aussi bien des versions spécifiques (Internet Explorer 8) que des parts de marché (tous les navigateurs avec plus de 5 % de parts de marché).
L’exemple suivant illustre les alertes relevées par doiuse dans le cas d’une recherche de compatibilité avec Internet Explorer 6 et Internet Explorer 7 :
../node_modules/.bin/doiuse -b 'ie < 8' sample.css sample.css:1:1: CSS 2.1 selectors not supported by: IE (6) sample.css:8:1: CSS 2.1 selectors not supported by: IE (6) sample.css:12:1: CSS3 Transitions not supported by: IE (6,7) sample.css:14:1: CSS 2.1 selectors not supported by: IE (6)
5. Optimiser notre code
Commentaires, indentations ou encore noms de variables : tout cela occupe de la place – autant d’octets transférés sur le réseau avant d’être exécutés par un client web. Les outils d’optimisation offrent l’opportunité aux développeurs et développeuses d’écrire du code sans compromettre sa lisibilité et sa maintenabilité.
Les minifieurs et optimiseurs mettent en œuvre différentes techniques pour réduire le poids de notre code :
-
suppression des commentaires et caractères non significatifs ;
-
renommage de variables ;
-
factorisation d’occurrences multiples similaires ;
-
suppression des instructions relatives au débogage/développement ;
-
suppression du code inutilisé ;
-
écriture automatique de code pour prendre en charge des environnements anciens ou futurs.
5.1. uglify-es
UglifyJS (npmjs.com/uglify-es) est un des premiers compresseurs à utiliser une représentation syntaxique en arbre (Abstract Syntax Tree – AST) en lieu et place des classiques optimisations avec expressions régulières.
Cette méthode élargit les perspectives de la compression via de la réécriture de code :
-
hoisting des variables (remontée de leur déclaration en début de portée) ;
-
combinaison des déclarations de variables ;
-
factorisation des valeurs de variables ;
-
réécriture partielle d’expressions ;
-
injection en ligne du contenu de variables.
UglifyJS s’utilise en ligne de commande ou comme un module Node.
5.2. postcss
PostCSS (npmjs.com/postcss) est une optimiseur CSS modulaire. Cet outil est construit autour d’un parseur CSS, d’un arbre syntaxique et d’un compilateur de texte. C’est la même recette qui a participé au succès et à la richesse fonctionnelle d’outils comme UglifyJS et ESLint.
Avec une ou plusieurs extension(s), vous basculez d’un optimiseur de code vers la possibilité de créer votre propre préprocesseur, comme Sass !
5.3. autoprefixer
autoprefixer (npmjs.com/autoprefixer) est le module qui
vous épargnera l’écriture de centaines de lignes CSS.
Il ajoute automatiquement les préfixes navigateurs aux bons endroits :
-webkit
, -moz
, etc.
autoprefixer s’utilise comme extension au module PostCSS, en ligne de commande ou comme module Node.
../node_modules/.bin/postcss sample.css \ --use autoprefixer | grep transition transition: font-weight 0.2s ease;
Le choix de compatibilité avec les navigateurs repose sur la variable
d’environnement BROWSERSLIST
, gérée par le module browserslist
(npmjs.com/browserslist) :
export BROWSERSLIST='firefox > 8' ../node_modules/.bin/postcss sample.css \ --use autoprefixer | grep transition -moz-transition: font-weight 0.2s ease; transition: font-weight 0.2s ease;
5.4. uncss
uncss (npmjs.com/uncss) est le pendant inverse d'autoprefixer puisqu’il se charge de supprimer le code CSS inutilisé. Il s’utilise de manière autonome ou comme module PostCSS.
Le module charge une ou plusieurs page(s) web, calcule la différence entre les règles utilisées et celles qui ne le sont pas. Vous êtes libre de mentionner une liste blanche de règles à ne jamais supprimer.
5.5. csswring
csswring (npmjs.com/csswring) est un minifieur de code CSS qui s’interface lui aussi avec PostCSS. Vous lui donnez du code, il en ressort une version avec le minimum de caractères possible.
5.6. google-closure-compiler-js
Google Closure Compiler (npmjs.com/google-closure-compiler-js) est un compilateur ECMAScript plus poussé qu'UglifyJS mais qui impose un style d’écriture plus strict, voire plus contraignant. Ses optimisations sont en général bien plus poussées et permettent d’atteindre des niveaux de finesse difficiles à obtenir autrement.
5.7. csso
csso (npmjs.com/csso) est une alternative à csswring, écrite par l’équipe derrière la méthodologie BEM (en.bem.info).
csso ira jusqu’à réécrire les codes couleurs, les margin
et padding
et
factorisera les sélecteurs similaires.
5.8. svgo
svgo (www.npmjs.com/svgo) s’attaque au nettoyage des fichiers graphiques vectoriels au format SVG. Il simplifie les chemins et supprime les attributs et déclarations superflues.
Vous pouvez l’essayer en ligne sur jakearchibald.github.io/svgomg/ ou l’intégrer comme extension à PostCSS.
5.9. wawoff2
wawoff2 (npmjs.com/wawoff2) optimise des polices de caractères pour le Web. Le module convertit des polices au format TTF vers le format WOFF2 – à préférer car plus léger et donc rapide à charger.
6. Passer d’un langage à un autre
Les préprocesseurs sont des outils de productivité pour CSS. Ils transforment un langage plus avancé dans quelque chose qui est compris par un navigateur web.
La même chose s’applique avec la compilation ou la transpilation pour ECMAScript, pour utiliser dès maintenant une version du futur.
6.1. less
less (npmjs.com/less) est un préprocesseur CSS. Il gère des variables, des mixins, des calculs de couleurs et des fonctions qui encouragent une écriture modulaire, plus logique et plus succincte.
@warning-color: red;
@base-font-size: 18px;
.btn {
border: 1px solid black;
border-radius: @base-font-size / 6;
font-size: @base-font-size;
&--large {
font-size: @base-font-size * 1.5;
}
&--warning {
border-color: fadeout(@warning-color, 10%);
color: @warning-color;
}
}
L’exécutable lessc
compile le fichier less:
../node_modules/.bin/lessc stylesheet.less
6.2. sass
sass (npmjs.com/node-sass) est un autre préprocesseur CSS. Il est issu du monde Ruby et est désormais tout aussi puissant dans Node grâce à LibSass, un module rapide et portable écrit en C++.
6.3. browserify
browserify (npmjs.com/browserify) transforme des modules et du code initialement écrit pour Node vers du code exécutable dans un navigateur web.
Un puissant mécanisme de transformations étend ses capacités au coup par coup.
💬
|
Nous en parlons plus en détail dans la section
“Importer des modules |
6.4. babel
babel (npmjs.com/babel) est un outil qui permet de passer d’une version d’ECMAScript à une autre, fonctionnalité par fonctionnalité. C’est un outil indispensable pour écrire un code moderne et le faire fonctionner dans des navigateurs anciens.
6.5. typescript
TypeScript (npmjs.com/typescript) est un langage de programmation typé. Toute structure utilisée est décrite avec un schéma que TypeScript valide. Nous sommes prévenu·e·s des erreurs avant même d’avoir exécuté notre code car l’outillage sait si on manipule des données qui existent.
Au final, le code est transformé en ECMAScript et exécuté en tant que tel. Le code est tellement propre que nous pouvons arrêter d’utiliser TypeScript du jour au lendemain et travailler sur le code qu’il aura généré sans aucun problème.
7. Gérer des fichiers
Ces bibliothèques nous aident à écrire moins de lignes de code pour des besoins quotidiens de manipulation de fichiers.
7.1. mkdirp
mkdirp (npmjs.com/mkdirp) est identique à la
commande Unix mkdir -p
, c’est-à-dire que les répertoires seront créés récursivement
s’ils n’existent pas au préalable.
Si nous utilisions le module Node fs
, nous devrions créer l’arborescence de
répertoires par nous-même, niveau par niveau.
7.2. rimraf
rimraf (npmjs.com/rimraf) est le pendant opposé de mkdirp.
Il supprime une arborescence de manière récursive.
C’est l’équivalent de la commande Unix rm -rf
.
Si nous utilisions le module Node fs
, nous devrions supprimer d’abord
les fichiers puis les répertoires, un par un.
7.3. glob
glob (npmjs.com/glob) est un utilitaire pour obtenir une liste de fichiers en utilisant des motifs.
'use strict';
const {promisify} = require('util');
const glob = promisify(require('glob'));
glob('*.js').then(console.log); // (1)
glob('re*.js').then(console.log); // (2)
glob('sample.*').then(console.log); // (3)
-
Affiche une liste de fichiers dont l’extension est
.js
. -
Affiche une liste de fichiers qui commencent par
re
et dont l’extension est.js
. -
Affiche une liste de fichiers qui s’appellent
sample
, peu importe leur extension.
7.4. fs-extra
fs-extra (npmjs.com/fs-extra) est une collection de fonctions pour gérer les opérations de fichiers. Le module inclut rimraf et mkdirp en plus d’autres fonctions récursives, pour copier, déplacer ou supprimer des fichiers.
7.5. graceful-fs
graceful-fs (npmjs.com/graceful-fs) est identique
au module Node fs
.
La différence se situe sous le capot : le module gère les défaillances du système et tente d’accéder à nouveau aux ressources demandées si les erreurs sont liées à des problèmes de performance.
C’est un module à utiliser si notre application dépend fortement de la disponibilité du système de fichiers et si celui-ci est fortement sollicité.
7.6. chokidar
chokidar (npmjs.com/chokidar) crée des observateurs du système de fichiers. Il gère les différences des systèmes d’exploitation et nous permet d’écrire un seul et même code.
C’est la bibliothèque vers laquelle se tourner lorsque nous avons besoin de déclencher des actions quand des fichiers sont modifiés.
8. Stocker dans des bases de données
Node sait communiquer avec tout type de bases de données grâce à l’écosystème npm
.
Préférez les modules faisant état de pilote natif/binaire –
le transfert de données n’en sera que plus rapide.
8.1. db-migrate
db-migrate (npmjs.com/db-migrate) est un outil de gestion de migrations pour MySQL, SQLite, MongoDB et PostgreSQL. À l’aide de scripts de migration, il rend reproductibles des changements de structure dans une base de données – ajout ou suppression de champ, de table ou d’index.
8.2. knex
knex (npmjs.com/knex) propose d’interagir et d’interroger des bases de données SQL comme PostgreSQL, MariaDB, MySQL et SQLite.
Les requêtes s’écrivent en SQL pur ou en utilisant une API dite “fluide”, pour ne pas écrire le SQL à la main.
'use strict';
const {join} = require('path');
const db = require('knex')({
client: 'sqlite3', // (1)
connection: {
filename: join(__dirname, 'sample.sqlite') // (2)
}
});
Promise.all([
db('books').where('title', 'like', '%Node%'), // (3)
db('books').count('title as count').first(), // (4)
])
.then(([rows, count]) => {
console.log(rows); // (5)
console.log(count); // (6)
db.destroy();
});
-
Indique que nous allons nous connecter à une base de données de type SQLite.
-
Spécifie l’emplacement de la base de données.
-
Effectue une recherche floue sur les lignes dont le titre contient le mot
'Node'
. -
Compte le nombre de lignes et retourne le premier (et seul) résultat de la requête.
-
Affiche
[ { id: 1, title: 'Node.js ', created_at: '2018-07-11 10:34:33' } ]
. -
Affiche
{ count: 3 }
.
8.3. bookshelf
bookshelf (npmjs.com/bookshelf) est une surcouche à Knex, écrite par les mêmes personnes. Elle modélise les données sous forme d’objets et de schémas (ORM) pour automatiser des actions et ajouter plus d'“intelligence” à notre modèle de données.
8.4. sequelize
sequelize (npmjs.com/sequelize) est une alternative à Knex et à Bookshelf. Elle gère des schémas de données de manière optionnelle, mais aussi les migrations. Ces dernières permettent de scripter les changements de structure d’une base de données, de les tester en local avant de les jouer en production.
8.5. mongoose
mongoose (npmjs.com/mongoose) sert à composer des modèles de données pour la base de données MongoDB – dite NoSQL. Elle définit des comportements annexes comme des mixins ou des accesseurs dynamiques.
8.6. levelup
LevelDB (npmjs.com/levelup) est un système de bases de
données clé/valeur extrêmement modulaire.
Le stockage se fait sur disque par défaut, mais il peut évoluer vers du stockage
en mémoire (module memdown
) ou même dans un navigateur web (avec IndexedDB).
'use strict';
const levelup = require('levelup');
const memdown = require('memdown');
const encode = require('encoding-down');
const db = levelup(encode(memdown(), // (1)
{ valueEncoding: 'json' }
));
Promise.all([
db.put('node', {title: 'Node.js'}),
db.put('css', {title: 'CSS maintenables'}),
db.put('opensky', {title: 'Open Sky'}),
])
.then(() => db.get('node')) // (2)
.then(result => {
console.log(result); // (3)
});
-
Crée la connexion à la base de données en mémoire.
-
Recherche un enregistrement après l’avoir enregistré en mémoire.
-
Affiche
{ title: 'Node.js' }
.
8.7. redis
redis (npmjs.com/redis) est un gestionnaire de bases de données clés/valeurs distribuées et performantes.
'use strict';
const client = require('redis').createClient();
const hset = require('util').promisify(client.hset);
Promise.all([
hset('book:node', 'title', 'Node.js'),
hset('book:css', 'title', 'CSS maintenables'),
hset('book:opensky', 'title', 'Open Sky')
])
.then(() => {
console.log('Enregistrements créés.');
client.end();
});
hiredis (npmjs.com/hiredis) est un pilote C++ qui augmente les performances de connexion à une base de données redis.
8.8. elasticsearch
elasticsearch (npmjs.com/elasticsearch) est un client pour simplifier la connexion à une base de données Elasticsearch. Une base de ce type est particulièrement adaptée à l’indexation des données, pour des recherches performantes et complexes.
9. Ligne de commande
Ces modules complètent le panorama déjà très varié présenté dans le chapitre 8.
9.1. yargs-parser
yargs-parser (npmjs.com/yargs-parser) est le module d’interprétation des arguments utilisé par le module yargs. C’est une alternative plus puissante et plus complexe que minimist.
9.2. args
args (npmjs.com/args) est un module minimaliste pour interpréter les arguments, les structurer et afficher une aide claire à nos utilisateurs et utilisatrices.
Cerise sur le gâteau : le module suggère un choix de commande en cas d’erreur de frappe.
9.3. caporal
caporal (npmjs.com/caporal) est un framework complet pour bâtir des applications en ligne de commandes. Il gère les classiques arguments et options ainsi que les sous-commandes, les types de valeurs et l’autocomplétion.
9.4. promptly
promptly (npmjs.com/promptly) est un utilitaire pour poser des questions, valider et travailler avec les réponses obtenues. Il est minimaliste et a un faible nombre de dépendances.
9.5. supports-color
supports-color (npmjs.com/supports-color) vérifie si le contexte d’exécution du programme en ligne de commande supporte les couleurs.
Cela nous évite d’envoyer des codes ANSI, qui, seraient affichés au lieu d’être interprétés comme des couleurs.
10. Applications web
Ces modules complètent le panorama déjà très varié présenté dans le chapitre 7.
10.1. fastify
fastify (npmjs.com/fastify) est un framework inspiré de Express. Il se focalise sur la simplicité de l’expérience de développement et sur de hautes performances. Il sait valider les données sortantes à l’aide de schémas.
Pour aller au-delà des données, il se combine avec le module point-of-view (npmjs.com/point-of-view). Vous avez ainsi accès à l’utilisation de modules de templating.
10.2. passport
passport (npmjs.com/passport) est une bibliothèque modulaire d’authentification pour Express. Elle se branche à différents mécanismes pour vérifier les utilisateurs : utilisateur et mot de passe, compte GitHub, Twitter, OAuth, etc.
Les sessions d’utilisateurs se gèrent à côté – pour mémoriser qui est connecté ou non, et avec quel identifiant sécurisé et unique.
Référez-vous à sa documentation pour des exemples détaillés d’utilisation.
10.3. restify
restify (npmjs.com/restify) est un framework web spécialisé dans la création d’API HTTP.
Il gère les versions de routes et expose un client permettant de consommer des données sur d’autres API REST – proxy.
'use strict';
const restify = require('restify');
const {NotFoundError} = require('restify-errors');
const server = restify.createServer();
const countries = require('i18n-iso-countries');
const responseV1 = (request, response, next) => {
const codes = countries.getNames('en');
if (codes[request.params.code] === undefined) {
return next(new NotFoundError('Country not found'));
}
response.send(200, codes[request.params.code]);
next();
};
server.get({ path: '/:code', version: '1.0.0' }, responseV1);
server.listen(8080, () => {
console.log('Serveur accessible sur %s', server.url);
});
10.4. faye
faye (npmjs.com/faye) est un serveur WebSocket pour communiquer en temps réel entre un client et un serveur. Il sait débrayer vers Ajax ou JSON-P pour les navigateurs anciens qui ne comprennent pas WebSocket.
'use strict';
const http = require('http');
const faye = require('faye');
const ws = new faye.NodeAdapter({
mount: '/realtime', timeout: 10
});
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Tyoe': 'text/plain' });
res.end('Contenu non temps réel');
});
ws.attach(server);
server.listen(3000);
Cet exemple de serveur minimaliste expose un point d’entrée auquel on peut accéder via le client Faye, dans un navigateur ou via un autre script Node.
Tout message émit par un client sera relayé auprès des autres clients connectés.
10.5. swagger-client
swagger-client (npmjs.com/swagger-client) sert à valider des requêtes et des réponses HTTP en fonction de schémas qui répondent à la spécification OpenAPI.
Cette spécification permet entre autres de gérer automatiquement les routes de notre application pour nous concentrer sur le code qui génère les données de sortie.
11. Modules front-end et templating
Les bibliothèques de templating proposent d’associer une structure de données à une logique de présentation. Pour la plupart, elles fonctionnent aussi bien sous Node que dans les navigateurs, ce qui est une excellente nouvelle pour partager des comportements d’affichage entre les deux environnements.
Tous les modules que nous allons voir généreront cette sortie HTML :
<!DOCTYPE html>
<html>
<head>
<title>Template demo</title>
</head>
<body>
<ul>
<li>CSS maintenables</li>
<li>Node.js</li>
<li>Open Sky</li>
</ul>
</body>
</html>
11.1. nunjucks
nunjucks (npmjs.com/nunjucks) est un portage de Jinja, bibliothèque bien connue par les adeptes de Python. Sa syntaxe inclut des fonctionnalités comme les filtres, les blocs ou l’héritage de gabarit.
<!DOCTYPE html>
<html>
<head>
<title>{{ title | default('Template demo') | capitalize }}</title>
</head>
<body>
{% set items = ['Node.js', 'CSS maintenables', 'Open Sky'] -%}
<ul>
{% for item in items|sort -%}
<li>{{ item }}</li>
{% endfor -%}
</ul>
</body>
</html>
11.2. handlebars
handlebars (npmjs.com/handlebars) et son prédécesseur mustache sont les vétérans du templating Node. Leur parti pris est de proposer le minimum de logique afin que celle-ci reste au plus près des données.
handlebars sait aussi précompiler les gabarits sous forme de fonctions ECMAScript.
<!DOCTYPE html>
<html>
<head>
<title>{{#if title}}{{title}}{{else}}Template demo{{/if}}</title>
</head>
<body>
<ul>
{{#each items}}
<li>{{.}}</li>
{{/each}}
</ul>
</body>
</html>
11.3. pug
pug (npmjs.com/pug) opte pour un parti minimaliste qui repose entièrement sur l’indentation. Son mécanisme de blocs facilite la réutilisation d’éléments de présentation.
doctype html
html
head
title= title || 'Template demo'
body
ul
each item in ['Node.js', 'CSS maintenables', 'Open Sky']
li= item
11.4. ejs
ejs (npmjs.com/ejs) part du principe qu’il n’y a pas besoin d’un langage de templating autre qu’ECMAScript. Donc c’est tout simplement ce qui vous sera proposé, impliquant de ce fait une faible courbe d’apprentissage.
<!DOCTYPE html>
<html>
<head>
<title><%= typeof title === 'string' ? title : 'Template demo' %></title>
</head>
<body>
<ul>
<% ['Node.js', 'CSS maintenables', 'Open Sky'].forEach((item) => { -%>
<li><%= item %></li>
<% }); -%>
</ul>
</body>
</html>
11.5. react
React (npmjs.com/react) est une bibliothèque de présentation dite “réactive” et orientée composants. Elle génère un arbre visuel à partir de données passées en entrée. Cet arbre est ensuite transformé en HTML, en interface iOS ou Android, entre autres.
'use strict';
const React = require('react');
const BookList = ({books=[]}) => {
return (<ul>
{books.map((bookName, i) => (
<li key={i}>{bookName}</li>
))}
</ul>);
}
module.exports = ({title, books}) => {
return (
<html>
<head>
<title>{title || 'Template demo'}</title>
</head>
<body>
<BookList books={books} />
</body>
</html>
);
};
11.6. storybook
storybook (github.com/storybooks/storybook) complète React et d’autres frameworks de templating en créant un catalogue de composants auto-documentés. Les composants sont affichés en même temps que le code nécessaire pour les utiliser dans une autre application.
12. Tester notre code
Le module assert
intégré à Node suffit pour démarrer.
Il existe cependant tout un outillage pour tester notre code à destination de
Node (tests unitaires) ou des navigateurs (tests fonctionnels) ainsi que pour
écrire des assertions plus facilement.
12.1. tape
tape (npmjs.com/tape) est une bibliothèque d’exécution de tests minimaliste qui se base sur le Test Anything Protocol (TAP, testanything.org). Elle embarque aussi le minimum vital pour écrire des assertions.
'use strict';
const test = require('tape');
test('Date test', (t) => { // (1)
t.plan(1);
t.ok(Date.now() > new Date('2013-03-24').getTime()); // (2)
});
-
Création d’un test.
-
Écriture d’une assertion.
12.2. chai
chai (npmjs.com/chai) est une bibliothèque poussée d’assertions. Son mécanisme chaîne permet de quasiment écrire des phrases pour exprimer l’intention des choses à vérifier.
'use strict';
const {expect} = require('chai');
expect([1, 2]).to.be.an('array'); // (1)
expect([1, 2]).to.deep.equal([1, 2]); // (2)
expect({}).to.be.an('object').and.to.be.empty;// (3)
-
Vérification du type d’une variable.
-
Vérification stricte de valeur d’une variable.
-
Double vérification – il s’agit bien d’objet et il est vide, sans clé/valeur.
12.3. sinon
sinon (npmjs.com/sinon) est un compagnon idéal pour intercepter le fonctionnement interne de variables et d’objets. Le module propose de créer des écouteurs (spys) et des bouchons (stubs, mocks).
En d’autres termes, vous prenez la main sur des portions de votre propre code pendant la durée des tests. Ces techniques servent pour simuler des erreurs et différentes situations tout en observant le comportement réel de notre code.
'use strict';
const test = require('tape');
const sinon = require('sinon');
test('Date', (t) => {
const d = Date;
const dateTime = new Date('1983-03-24').getTime();
const stub = sinon.stub(d, 'now'); // (1)
stub.returns(9999999999999); // (2)
d.now();
t.equal(stub.calledOnce, true); // (3)
t.ok(stub.returnValues[0] > dateTime);
t.end();
});
-
Création d’un bouchon pour la méthode
now()
d’un objetDate
. -
Surcharge de la valeur retournée par la méthode
d.now()
. -
Nous constatons le nombre de fois où la méthode
d.now()
a été appelée.
Le module sinon-chai (npmjs.com/sinon-chai) intègre sinon avec le mécanisme d’assertions de chai.
12.4. nyc
nyc (npmjs.com/nyc) génère une couverture de code. Il inspecte le code exécuté pendant les tests et en déduit les portions qui n’ont pas été visitées et, donc, qui n’ont pas été testées. C’est un indicateur utile pour attester de la fiabilité d’une base de code – plus la couverture est importante, plus il y a de chances que les cas à la marge aient été vérifiés.
nyc se greffe sur n’importe quelle bibliothèque d’exécution de tests. Sous le capot, c’est le module istanbul (npmjs.com/istanbul) qui est utilisé pour effectuer les calculs de couverture de code.
12.5. karma
karma (npmjs.com/karma) pilote l’exécution de tests depuis un ou plusieur(s) navigateurs web. Ces derniers (Chrome, Safari, Firefox, etc.) se pilotent sur notre ordinateur, depuis une machine virtuelle (VirtualBox) ou même par le biais d’un service en ligne (SauceLabs, BrowserStack, etc.).
12.6. supertest
supertest (npmjs.com/supertest) sert à tester une interface HTTP. Le module envoie des requêtes et nos assertions vérifient qu’elles retournent bien ce qui est attendu – code HTTP, structure de réponse etc.
Je trouve ce module pratique pour tester des choses qui seraient difficiles à couvrir uniquement avec des tests unitaires.
13. Objets connectés
Node a bénéficié de l’engouement autour des objets connectés grâce à sa nature asynchrone et à sa légèreté. C’est une plate-forme de choix pour dialoguer ou embarquer dans des nano-ordinateurs, réfrigérateurs et autres ampoules connectées.
13.1. nitrogen
nitrogen (npmjs.com/nitrogen) gère les interactions entre différents périphériques, sur un même réseau local et à travers Internet.
La bibliothèque se base sur un mécanisme déclaratif de fonctionnalités et de terminaux ainsi que la publication de messages.
13.2. serialport
serialport (npmjs.com/serialport) est la bibliothèque de base pour communiquer avec le port série d’un appareil. Un câble USB suffit ensuite pour envoyer nos instructions à cet appareil.
13.3. firmata
firmata (npmjs.com/firmata) est un firmware, un protocole de communication, ainsi qu’une bibliothèque de communication pour microcontrôleur Arduino.
Le module Node apprend ainsi à communiquer avec un Arduino préalablement flashé avec Firmata. Cela nous permet notamment d’écrire des applications en JavaScript au lieu d’utiliser du C.
13.4. johnny-five
johnny-five (npmjs.com/johnny-five) est une bibliothèque haut niveau pour Arduino, Raspberry Pi et tout autre microcontrôleur. Elle simplifie les interactions avec des moteurs, des servo-contrôleurs, des capteurs etc.
13.5. node-red
node-red (npmjs.com/node-red) est une interface visuelle pour programmer des flux de données entre objets connectés. Le projet émane d’employé·e·s d’IBM.
L’exécutable démarre un serveur web dont l’interface nous sert à relier des sources de données, des réactions à des événements avec des objets prêts à recevoir les instructions.
14. Accessibilité
L’écosystème npm
a participé à un essor d’outillage lié à l’accessibilité
d’applications web.
Auparavant, les outils étaient difficilement automatisables.
14.1. a11y
a11y (npmjs.com/a11y) est un automate d’inspection de pages web. Il détecte des problèmes de contrastes, de calques qui masquent du contenu ou d’éléments qui ne seraient pas navigables au clavier, entre autres.
C’est un excellent outil pour améliorer la qualité d’une application tout en l’ouvrant à un public trop souvent mis de côté.
npx a11y https://thom4.net ✖ Controls and media elements should have labels #search > .form-control ✔ This element does not support ARIA roles ✔ Elements with ARIA roles must be in the correct scope ✔ This element has an invalid ARIA attribute ✔ ARIA state and property values must be valid
14.2. a11y.css
a11y.css (npmjs.com/a11y.css) est une feuille de styles CSS à injecter dans une page web pour rendre visible des incohérences. Parmi ces dernières, nous retrouvons des boutons sans intitulé, l’absence de langue du document ou encore l’absence de bouton de validation de formulaire ou de texte alternatif d’images.
14.3. lighthouse
lighthouse (npmjs.com/lighthouse) est l’outil d’analyse de performances, de référencement (SEO) et d’accessibilité embarqué dans le navigateur web Google Chrome.
Ce module npm
le rend utilisable depuis un terminal et écrit le rapport
dans un fichier HTML.
14.4. storybook-addon-a11y
storybook-addon-a11y (npmjs.com/storybook-addon-a11y) est une extension au module storybook. Le module signale les problèmes d’accessibilité au niveau de chaque composant. Le suivi est ainsi fait en continu, au plus proche des composants distribués et utilisés dans les applications.
15. Travailler avec des images, des sons et des vidéos
15.1. sharp
sharp (npmjs.com/sharp) est un module de redimensionnement et de transformation d’images JPG, PNG et WebP écrit en JavaScript et C++. Il ne nécessite pas de programme externe et est compatible avec une approche en flux.