UNPKG

nodebook

Version:

Node.js • Apprendre par la pratique. Familiarisez-vous avec JavaScript, Node.js et l'écosystème de modules npm. Apprenez à concevoir et à déployer des *applications web* et des *outils en ligne de commande*.

1,299 lines (1,214 loc) 172 kB
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="Asciidoctor 2.0.9"> <title>Sélection de modules&#160;npm</title> <style> #header, #content, #footer { margin: 2rem auto; max-width: 46rem; } #header { margin-top: 0; } .title, #toctitle { color: var(--dark-accent); } a { /* white-space: nowrap; */ } img, iframe, video, audio { max-width: 100%; } p { font-weight: normal; } /* Taken out from book.css */ dl dt { margin-bottom: 0.3125em; font-weight: bold; } dl dd { margin-bottom: 1.25em; } dt, th.tableblock, td.content, div.footnote { text-rendering: optimizeLegibility; } .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { overflow: auto; word-wrap: break-word; } .literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; } .listingblock { margin: 0 0 2em; } .listingblock > .content { position: relative; } .listingblock > .title { font-weight: bold; } .listingblock code[data-lang]::before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 1em; right: 1em; line-height: 1; text-transform: uppercase; color: #999; } .listingblock:hover code[data-lang]::before { display: block; } .listingblock.terminal pre .command::before { content: attr(data-prompt); padding-right: 0.5em; color: #999; } td.hdlist1, td.hdlist2 { vertical-align: top; padding-right: 0.625em; } td.hdlist1 { font-weight: bold; } .literalblock + .colist, .listingblock + .colist { margin-top: -1.5em; } .colist td:not([class]):first-child { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; } .colist td:not([class]):first-child img { max-width: none; } .colist td:not([class]):last-child { padding: 0.25em 0; } /* Custom classes */ .line-through { text-decoration: line-through; } .RemarquePreTitre, #toctitle { font-style: normal; font-weight: bold; } .RemarquePreTitre::after { content: "•"; padding-left: 5px; } .admonitionblock { } .admonitionblock > table, .exampleblock { --commented: rgba(17, 17, 68, .65); --border-radius-base: 8px; background-color: #fafafa; border: 1px solid var(--dark-shade); border-left: none; border-right: none; margin: 1.5em 0; padding: 1em; } .exampleblock .title { font-weight: bold; } .icon .title { font-size: 2em; } .admonitionblock > table td.icon { display: none; vertical-align: middle; } @media screen and (min-width: 769px) { .admonitionblock > table td.icon { display: table-cell; } } .admonitionblock > table td.icon { padding-right: 1em; } .admonitionblock > table td.icon img { max-width: none; } .colist ol { margin-left: 1.5em; /* aligns with the listing edge */ padding-left: 0; font-weight: bold; /* makes it stand out more */ } .colist ol p { margin: 0 0 .5em; } .listingblock:not(.prismjs) pre, .language-bash.hljs { background: #323232; color: wheat; margin: 0; padding: 1rem; } .language-bash.hljs .hljs-built_in, .language-bash.hljs .hljs-builtin-name { color: white; } .language-bash.hljs .hljs-string { color: lightgreen; } .language-bash.hljs .hljs-variable { color: lightskyblue; } .keyseq { font-weight: normal; white-space: nowrap; } .language-bash.hljs .keyseq { color: white; } .language-bash.hljs kbd { background: transparent; box-shadow: none; color: white; font-size: 0.8em; font-weight: bold; padding: 0.1em 0.4em; } .listingblock pre.highlightjs, .listingblock pre.prismjs { background-color: transparent; margin: 0; padding: 0; } .listingblock pre.highlightjs > code, .listingblock pre.prismjs { border-left: 4px solid var(--dark-accent); padding-left: 1em; font-size: .8em; } .listingblock pre.highlightjs > code.language-bash { border-left-color: limegreen; } .token.comment .conum { font-weight: normal; } .hdlist .hdlist1 { text-align: right; white-space: nowrap; } td > p:first-child { margin-top: 0; } .hljs-comment { font-style: normal !important; } #toc.toc2 a { text-decoration: none; white-space: normal; } #toc.toc2 a:hover, #toc.toc2 a:focus { text-decoration: underline; } #toc.toc2 ul { list-style: none; } #toc.toc2 > ul { padding-left: 0; } #toc.toc2 ul ul { padding-left: 1em; } @media screen and (min-width: 769px) { body { padding-left: 25vw !important; } #header, #content, #footer { margin-left: 0; } #toc.toc2 { height: 100%; left: 0; max-width: 20vw; overflow: auto; padding: 1rem; position: fixed; top: 0; z-index: 1000; } #toc.toc2 > ul { font-size: 0.85em; } #toc li.active > a[href^="#"], [id]:target { background: #ffc; } } .admonitionblock.context-callout > table { border-width: 5px; border-color: var(--brand-color); } </style> <style type="text/css" class="prism-theme">/** * prism.js default theme for JavaScript, CSS and HTML * Based on dabblet (http://dabblet.com) * @author Lea Verou */ code[class*="language-"], pre[class*="language-"] { color: black; background: none; text-shadow: 0 1px white; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { text-shadow: none; background: #b3d4fc; } pre[class*="language-"]::selection, pre[class*="language-"] ::selection, code[class*="language-"]::selection, code[class*="language-"] ::selection { text-shadow: none; background: #b3d4fc; } @media print { code[class*="language-"], pre[class*="language-"] { text-shadow: none; } } /* Code blocks */ pre[class*="language-"] { padding: 1em; margin: .5em 0; overflow: auto; } :not(pre) > code[class*="language-"], pre[class*="language-"] { background: #f5f2f0; } /* Inline code */ :not(pre) > code[class*="language-"] { padding: .1em; border-radius: .3em; white-space: normal; } .token.comment, .token.prolog, .token.doctype, .token.cdata { color: slategray; } .token.punctuation { color: #999; } .namespace { opacity: .7; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: #905; } .token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: #690; } .token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string { color: #9a6e3a; background: hsla(0, 0%, 100%, .5); } .token.atrule, .token.attr-value, .token.keyword { color: #07a; } .token.function, .token.class-name { color: #DD4A68; } .token.regex, .token.important, .token.variable { color: #e90; } .token.important, .token.bold { font-weight: bold; } .token.italic { font-style: italic; } .token.entity { cursor: help; } </style> <link rel="stylesheet" href="https://oncletom.io/styles/blog.css?v=v3.3.2"> <!-- WebMentions --> <link rel="pingback" href="https://webmention.io/oncletom.io/xmlrpc"> <link rel="webmention" href="https://webmention.io/oncletom.io/webmention"> <!-- Open Graph --> <meta property="og:type" content="book"> <meta property="og:image" content="https://oncletom.io/images/publications/nodejs-cover.png"> <meta property="og:book:author" content="Thomas Parisot"> <meta property="og:book:isbn" content="978-2212139938"> <meta property="og:book:release_date" content="2018-12-06"> <meta property="og:book:tag" content="Node.js"> <meta property="og:book:tag" content="JavaScript"> <meta property="og:book:tag" content="npm"> <meta property="og:book:tag" content="Développement front-end"> <meta property="og:book:tag" content="Développement back-end"> <meta property="og:locale" content="fr_FR"> <meta property="og:site_name" content="Node.js • Apprendre par la pratique"> <!-- Twitter OpenGraph --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@oncletom"> <meta name="twitter:creator" content="@oncletom"> <style type="text/css" class="extension-interactive-runner">[data-interactive-runtime="loaded"] .interactive--javascript code[data-lang]:before { background-color: #fcfcfc; border: 1px solid #0c2; border-radius: 1px; color: #0c2; cursor: pointer; display: inline-block; font-weight: bold; padding: .5em 1em; top: -2em; } [lang="en"] [data-interactive-runtime="loaded"] .interactive--javascript code[data-lang]:before { content: "▶ run code"; } [lang="fr"] [data-interactive-runtime="loaded"] .interactive--javascript code[data-lang]:before { content: "▶ voir le résultat"; } .interactive--javascript code[data-label]:before { content: attr(data-label); } .interactive iframe { position: absolute; visibility: hidden; } .interactive.status--loaded iframe { position: inherit; visibility: visible; } .interactive.status--loading { opacity: .5; } </style> <script class="extension-interactive-runner"> (function(d){ document.addEventListener('DOMContentLoaded', function(){ const script = d.createElement('script'); script.src = 'https://embed.runkit.com/'; script.async = true; script.onload = function(){ function makeListingInteractive (element){ if (element.classList.contains('interactive--installed') || element.classList.contains('status--loading')) { return; } const code = element.querySelector('code'); const nodeVersion = /interactive--runtime--node-([^\s]+)/.exec(element.className)[1]; const isEndpoint = element.classList.contains('interactive--endpoint'); const mode = isEndpoint ? 'endpoint' : null; let preamble = ''; const source = code .textContent .replace(/\/\/\s*\(\d+\)$/gm, '') .replace(/^["']?use strict["'][; ]*\n/, ''); if (isEndpoint) { preamble = `process.nextTick(() => { if (typeof module.exports === 'function') { exports.endpoint = module.exports; } else if (typeof server !== 'undefined') { exports.endpoint = server.listeners("request").pop(); } });` } element.classList.add('status--loading'); // eslint-disable-next-line no-undef RunKit.createNotebook({ nodeVersion, element, source, mode, preamble, onLoad: function(ntbk) { element.classList.add('interactive--installed'); element.classList.remove('status--loading'); element.classList.add('status--loaded'); code.parentNode.setAttribute('hidden', true); ntbk.evaluate(); } }); } function installEvents () { function getParent(el, condition) { let parent = el; while(parent = parent.parentNode) { if (condition(parent)) { return parent; } } } function hasClass(className) { return function check(el) { return el.classList.contains(className); } } document.querySelector('body').addEventListener('click', function(el) { if (el.target.classList.contains('language-javascript') || el.target.classList.contains('language-js')) { const parentNode = getParent( el.target, hasClass('interactive--javascript') ); makeListingInteractive(parentNode); } }); } installEvents(); document.body.dataset.interactiveRuntime = 'loaded'; }; document.body.appendChild(script); }); })(document);</script> <style type="text/css"> .listingblock [data-bash-subs]::before { content: attr(data-bash-subs) " "; opacity: .5; } .listingblock [data-bash-conum]::before { content: "(" attr(data-bash-conum) ")"; font-weight: bold; opacity: .7; }</style> <script> (function(d){ d.addEventListener('DOMContentLoaded', function(){ const {origin} = window.location; Array.from(document.querySelectorAll('a[href]')) .filter(link => link.href.indexOf(origin) !== 0) .forEach(link => { link.setAttribute('target', '_blank'); link.setAttribute('rel', 'noopener'); }); }); })(document);</script> <script> (function(d){ d.addEventListener('DOMContentLoaded', function(){ const script = d.createElement('script'); script.src = 'https://unpkg.com/menuspy@1.3.0/dist/menuspy.js'; script.async = true; script.onload = () => new MenuSpy(document.querySelector('#toc'), {enableLocationHash: false}); d.body.appendChild(script); }); })(document);</script> <style type="text/css"> #toc li.active > a[href^="#"] { font-weight: bold; } #toc li.active > a[href^="#"]::before { content: "▶ "; display: inline-block; position: absolute; margin-left: -1.2em; font-size: .8em; margin-top: 3px; } </style> </head> <body class="book toc2 toc-left"> <div id="header"> <h1>Sélection de modules&#160;npm</h1> <div id="toc" class="toc2"> <div id="toctitle">Table des matières</div> <ul class="sectlevel1"> <li><a href="#boîte_à_outils_du_quotidien">1. Boîte à outils du quotidien</a> <ul class="sectlevel2"> <li><a href="#lodash">1.1. lodash</a></li> <li><a href="#he">1.2. he</a></li> <li><a href="#chance">1.3. chance</a></li> <li><a href="#date_fns">1.4. date-fns</a></li> <li><a href="#tcomb">1.5. tcomb</a></li> <li><a href="#eventemitter3">1.6. eventemitter3</a></li> </ul> </li> <li><a href="#dev">2. Pendant le développement</a> <ul class="sectlevel2"> <li><a href="#debug">2.1. debug</a></li> <li><a href="#nodemon">2.2. nodemon</a></li> <li><a href="#npm_run_all">2.3. npm-run-all</a></li> <li><a href="#husky">2.4. husky</a></li> <li><a href="#onchange">2.5. onchange</a></li> <li><a href="#tiny_lr">2.6. tiny-lr</a></li> <li><a href="#livereactload">2.7. livereactload</a></li> </ul> </li> <li><a href="#protéger_nos_applications">3. Protéger nos applications</a> <ul class="sectlevel2"> <li><a href="#sanitize_filename">3.1. sanitize-filename</a></li> <li><a href="#helmet">3.2. helmet</a></li> <li><a href="#dompurify">3.3. dompurify</a></li> <li><a href="#filenamify">3.4. filenamify</a></li> <li><a href="#retire_js">3.5. retire.js</a></li> <li><a href="#snyk">3.6. snyk</a></li> </ul> </li> <li><a href="#vérifier_la_syntaxe_de_notrecode">4. Vérifier la syntaxe de notre&#160;code</a> <ul class="sectlevel2"> <li><a href="#htmlhint">4.1. htmlhint</a></li> <li><a href="#eslint">4.2. eslint</a></li> <li><a href="#csslint">4.3. csslint</a></li> <li><a href="#doiuse">4.4. doiuse</a></li> </ul> </li> <li><a href="#optimize">5. Optimiser notre&#160;code</a> <ul class="sectlevel2"> <li><a href="#uglify_es">5.1. uglify-es</a></li> <li><a href="#postcss">5.2. postcss</a></li> <li><a href="#autoprefixer">5.3. autoprefixer</a></li> <li><a href="#uncss">5.4. uncss</a></li> <li><a href="#csswring">5.5. csswring</a></li> <li><a href="#google_closure_compiler_js">5.6. google-closure-compiler-js</a></li> <li><a href="#csso">5.7. csso</a></li> <li><a href="#svgo">5.8. svgo</a></li> <li><a href="#wawoff2">5.9. wawoff2</a></li> </ul> </li> <li><a href="#transpiling">6. Passer d&#8217;un langage à un autre</a> <ul class="sectlevel2"> <li><a href="#less">6.1. less</a></li> <li><a href="#sass">6.2. sass</a></li> <li><a href="#browserify">6.3. browserify</a></li> <li><a href="#babel">6.4. babel</a></li> <li><a href="#typescript">6.5. typescript</a></li> </ul> </li> <li><a href="#fs">7. Gérer des fichiers</a> <ul class="sectlevel2"> <li><a href="#mkdirp">7.1. mkdirp</a></li> <li><a href="#rimraf">7.2. rimraf</a></li> <li><a href="#glob">7.3. glob</a></li> <li><a href="#fs_extra">7.4. fs-extra</a></li> <li><a href="#graceful_fs">7.5. graceful-fs</a></li> <li><a href="#chokidar">7.6. chokidar</a></li> </ul> </li> <li><a href="#databases">8. Stocker dans des bases de données</a> <ul class="sectlevel2"> <li><a href="#db_migrate">8.1. db-migrate</a></li> <li><a href="#knex">8.2. knex</a></li> <li><a href="#bookshelf">8.3. bookshelf</a></li> <li><a href="#sequelize">8.4. sequelize</a></li> <li><a href="#mongoose">8.5. mongoose</a></li> <li><a href="#levelup">8.6. levelup</a></li> <li><a href="#redis">8.7. redis</a></li> <li><a href="#elasticsearch">8.8. elasticsearch</a></li> </ul> </li> <li><a href="#cli">9. Ligne de commande</a> <ul class="sectlevel2"> <li><a href="#yargs_parser">9.1. yargs-parser</a></li> <li><a href="#args">9.2. args</a></li> <li><a href="#caporal">9.3. caporal</a></li> <li><a href="#promptly">9.4. promptly</a></li> <li><a href="#supports_color">9.5. supports-color</a></li> </ul> </li> <li><a href="#webapp">10. Applications&#160;web</a> <ul class="sectlevel2"> <li><a href="#fastify">10.1. fastify</a></li> <li><a href="#passport">10.2. passport</a></li> <li><a href="#restify">10.3. restify</a></li> <li><a href="#faye">10.4. faye</a></li> <li><a href="#swagger_client">10.5. swagger-client</a></li> </ul> </li> <li><a href="#templating">11. Modules front-end et templating</a> <ul class="sectlevel2"> <li><a href="#nunjucks">11.1. nunjucks</a></li> <li><a href="#handlebars">11.2. handlebars</a></li> <li><a href="#pug">11.3. pug</a></li> <li><a href="#ejs">11.4. ejs</a></li> <li><a href="#react">11.5. react</a></li> <li><a href="#storybook">11.6. storybook</a></li> </ul> </li> <li><a href="#testing">12. Tester notre code</a> <ul class="sectlevel2"> <li><a href="#tape">12.1. tape</a></li> <li><a href="#chai">12.2. chai</a></li> <li><a href="#sinon">12.3. sinon</a></li> <li><a href="#nyc">12.4. nyc</a></li> <li><a href="#karma">12.5. karma</a></li> <li><a href="#supertest">12.6. supertest</a></li> </ul> </li> <li><a href="#internet-of-things">13. Objets connectés</a> <ul class="sectlevel2"> <li><a href="#nitrogen">13.1. nitrogen</a></li> <li><a href="#serialport">13.2. serialport</a></li> <li><a href="#firmata">13.3. firmata</a></li> <li><a href="#johnny_five">13.4. johnny-five</a></li> <li><a href="#node_red">13.5. node-red</a></li> </ul> </li> <li><a href="#accessibilité">14. Accessibilité</a> <ul class="sectlevel2"> <li><a href="#a11y">14.1. a11y</a></li> <li><a href="#a11y_css">14.2. a11y.css</a></li> <li><a href="#lighthouse">14.3. lighthouse</a></li> <li><a href="#storybook_addon_a11y">14.4. storybook-addon-a11y</a></li> </ul> </li> <li><a href="#travailler_avec_des_images_des_sons_et_des_vidéos">15. Travailler avec des images, des sons et des vidéos</a> <ul class="sectlevel2"> <li><a href="#sharp">15.1. sharp</a></li> </ul> </li> </ul> </div> </div> <div id="content"> <div id="preamble"> <div class="sectionbody"> <div class="admonitionblock tip context-callout"> <table> <tr> <td class="icon"> <div class="title">💡</div> </td> <td class="content"> <div class="paragraph"> <p>Vous êtes en train de lire l&#8217;Annexe A du <a href="https://oncletom.io/node.js/">livre &#8220;Node.js&#8221;</a>, écrit par <a href="https://oncletom.io">Thomas Parisot</a> et publié aux <a href="https://editions-eyrolles.com/Livre/9782212139938">Éditions Eyrolles</a>.</p> </div> <div class="paragraph"> <p>L&#8217;ouvrage vous plaît&#160;? Achetez-le sur <a href="https://amzn.to/2E58PEw">Amazon.fr</a> ou en <a href="https://www.placedeslibraires.fr/livre/9782212139938">librairie</a>. <a href="https://opencollective.com/nodebook">Donnez quelques euros</a> pour contribuer à sa gratuité en ligne.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>Cette annexe est une sélection de modules&#160;<code>npm</code> (<span class="URL"><a href="https://npmjs.com" class="bare">npmjs.com</a></span>) à laquelle vous référer pour démarrer rapidement, mais aussi pour découvrir des usages et des domaines d&#8217;application insoupçonnés.</p> </div> <div class="paragraph"> <p>J&#8217;ai bâti cette liste à partir de mon expérience personnelle et sur la confiance que je porte aux personnes à l&#8217;origine de ces modules.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">💬</div> </td> <td class="content"> <div class="title"><span class="RemarquePreTitre">Remarque</span> Versions de Node et npm</div> <div class="paragraph"> <p>Le contenu de ce chapitre utilise les versions <strong>Node&#160;v10</strong> et <strong>npm&#160;v6</strong>. Ce sont les versions stables recommandées en&#160;2019.</p> </div> </td> </tr> </table> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <div class="title">💡</div> </td> <td class="content"> <div class="title"><span class="RemarquePreTitre">Pratique</span> Jouer avec les exemples dans un terminal</div> <div class="paragraph"> <p>Les exemples titrés d&#8217;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.</p> </div> <div class="listingblock"> <div class="title">Installation des exemples via le module npm <code>nodebook</code></div> <div class="content"> <pre><span data-bash-subs="$"></span>npm install --global nodebook <span data-bash-subs="$"></span>nodebook install appendix-a <span data-bash-subs="$"></span>cd $(nodebook dir appendix-a)</pre> </div> </div> <div class="paragraph"> <p>La commande suivante devrait afficher un résultat qui confirme que vous êtes au bon endroit&#160;:</p> </div> <div class="listingblock"> <div class="content"> <pre><span data-bash-subs="$"></span>node hello.js</pre> </div> </div> <div class="paragraph"> <p>Suivez à nouveau les instructions d&#8217;installation pour rétablir les exemples dans leur état initial.</p> </div> </td> </tr> </table> </div> </div> </div> <div class="sect1"> <h2 id="boîte_à_outils_du_quotidien">1. Boîte à outils du quotidien</h2> <div class="sectionbody"> <div class="paragraph"> <p>Ces modules répondent à des besoins quotidiens, pour travailler plus rapidement sur des structures ECMAScript.</p> </div> <div class="sect2"> <h3 id="lodash">1.1. lodash</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p><em>lodash</em> (<span class="URL"><a href="https://npmjs.com/lodash" class="bare">npmjs.com/lodash</a></span>) 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.</p> </div> <div class="paragraph"> <p>Vous pourrez ainsi filtrer, sélectionner, fusionner, vérifier et composer de nouvelles variables, aussi bien pour Node que dans les navigateurs.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">lodash.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> intersection<span class="token punctuation">,</span> first <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">DC</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'Batman'</span><span class="token punctuation">,</span> <span class="token string">'Brainiac'</span><span class="token punctuation">,</span> <span class="token string">'Thor'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">const</span> Marvel <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'Spiderman'</span><span class="token punctuation">,</span> <span class="token string">'Thor'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">first</span><span class="token punctuation">(</span><span class="token function">intersection</span><span class="token punctuation">(</span><span class="token constant">DC</span><span class="token punctuation">,</span> Marvel<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Affiche <code>Thor</code>.</p> </li> </ol> </div> </div> <div class="sect2"> <h3 id="he">1.2. he</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p><em>he</em> (<span class="URL"><a href="https://npmjs.com/he" class="bare">npmjs.com/he</a></span>) est un utilitaire pour encoder et décoder des entités HTML dans des chaînes de caractères.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">he.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span>encode<span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'he'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> html <span class="token operator">=</span> <span class="token string">'&lt;h1>Blog Post&lt;/h1>'</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(1)</b> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">encode</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Affiche <code>&lt;h1&gt;Blog Post&lt;/h1&gt;</code>.</p> </li> <li> <p>Affiche <code>&amp;#x3C;h1&amp;#x3E;Blog Post&amp;#x3C;/h1&amp;#x3E;</code>.</p> </li> </ol> </div> </div> <div class="sect2"> <h3 id="chance">1.3. chance</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p><em>chance</em> (<span class="URL"><a href="https://npmjs.com/chance" class="bare">npmjs.com/chance</a></span>) 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&#8217;anniversaire, des identifiants Android ou Apple, etc.</p> </div> <div class="paragraph"> <p>Il s&#8217;utilise surtout pour générer des données factices à des fins de tests, en attendant les vraies données.</p> </div> </div> <div class="sect2"> <h3 id="date_fns">1.4. date-fns</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>date-fns</em> (<span class="URL"><a href="https://npmjs.com/date-fns" class="bare">npmjs.com/date-fns</a></span>) est une collection de fonctions pour travailler avec des dates, plus facilement qu&#8217;avec l&#8217;objet natif&#160;<code>Date</code>.</p> </div> <div class="paragraph"> <p>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&#8217;une même semaine calendaire.</p> </div> </div> <div class="sect2"> <h3 id="tcomb">1.5. tcomb</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>tcomb</em> (<span class="URL"><a href="https://npmjs.com/tcomb" class="bare">npmjs.com/tcomb</a></span>) 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&#8217;ont pas la structure attendue.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">tcomb.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> t <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'tcomb'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">GPS</span> <span class="token operator">=</span> t<span class="token punctuation">.</span><span class="token function">struct</span><span class="token punctuation">(</span><span class="token punctuation">{</span> // <b class="conum">(1)</b> lat<span class="token punctuation">:</span> t<span class="token punctuation">.</span>Number<span class="token punctuation">,</span> lon<span class="token punctuation">:</span> t<span class="token punctuation">.</span>Number<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>strict<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> Bordeaux <span class="token operator">=</span> <span class="token constant">GPS</span><span class="token punctuation">(</span><span class="token punctuation">{</span> lat<span class="token punctuation">:</span> <span class="token number">44.8638</span><span class="token punctuation">,</span> lon<span class="token punctuation">:</span> <span class="token operator">-</span><span class="token number">0.6561</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> Crest <span class="token operator">=</span> <span class="token constant">GPS</span><span class="token punctuation">(</span><span class="token punctuation">{</span> lat<span class="token punctuation">:</span> <span class="token number">44.7311</span><span class="token punctuation">,</span> long<span class="token punctuation">:</span> <span class="token number">4.9861</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(2)</b> <span class="token keyword">const</span> Toulouse <span class="token operator">=</span> <span class="token constant">GPS</span><span class="token punctuation">(</span><span class="token punctuation">{</span> lat<span class="token punctuation">:</span> <span class="token number">43.6008</span><span class="token punctuation">,</span> lon<span class="token punctuation">:</span> <span class="token string">'r0s3'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(3)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Définition d&#8217;une structure stricte qui a pour propriétés <code>lat</code> et <code>lon</code>, pour <em>latitude</em> et <em>longitude</em>.</p> </li> <li> <p>Cet appel va lancer une exception car la propriété <code>long</code> est inconnue.</p> </li> <li> <p>Cet appel va lancer une exception car la propriété <code>lon</code> doit être un nombre.</p> </li> </ol> </div> </div> <div class="sect2"> <h3 id="eventemitter3">1.6. eventemitter3</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>eventemitter3</em> (<span class="URL"><a href="https://npmjs.com/eventemitter3" class="bare">npmjs.com/eventemitter3</a></span>) sert à gérer des événements de manière uniforme dans un script Node et dans les navigateurs.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">eventemitter3.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> EventEmitter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'eventemitter3'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> emitter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">EventEmitter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> emitter<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token parameter">data</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'on: %s'</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> emitter<span class="token punctuation">.</span><span class="token function">once</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token parameter">data</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'once: %s'</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>emitter<span class="token punctuation">.</span><span class="token function">listeners</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(1)</b> emitter<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token string">'ping'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(2)</b> emitter<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'pong'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(3)</b> emitter<span class="token punctuation">.</span><span class="token function">removeListener</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> emitter<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'pong'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(4)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Affiche <code>[ [Function], [Function] ]</code>.</p> </li> <li> <p>Affiche <code>on: ping,ping</code> puis <code>once: ping,ping</code>.</p> </li> <li> <p>Affiche <code>on: ping,ping</code>.</p> </li> <li> <p>N&#8217;affiche rien, l&#8217;événement étant désormais déconnecté.</p> </li> </ol> </div> </div> </div> </div> <div class="sect1"> <h2 id="dev">2. Pendant le développement</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="debug">2.1. debug</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>debug</em> (<span class="URL"><a href="https://npmjs.com/debug" class="bare">npmjs.com/debug</a></span>) rend optionnel l&#8217;affichage de messages de débogage. Les messages s&#8217;affichent en présence d&#8217;une variable d&#8217;environnement. Nous pouvons ainsi lancer un processus et retracer un cheminement complexe de données.</p> </div> <div class="paragraph"> <p>Par défaut, les messages ne s&#8217;affichent pas&#160;:</p> </div> <div class="listingblock"> <div class="content"> <pre><span data-bash-subs="$"></span>node examples/debug.js</pre> </div> </div> <div class="paragraph"> <p>Les messages du débogueur <code>app</code> s&#8217;affichent désormais&#160;:</p> </div> <div class="listingblock"> <div class="content"> <pre><span data-bash-subs="$"></span><mark>DEBUG=app</mark> node examples/debug.js app fromages [ 'livarot', 'chaource' ] +0ms</pre> </div> </div> <div class="paragraph"> <p>Nous pouvons en afficher plusieurs en même temps, en usant du caractère&#160;<code>*</code> ou en séparant les noms de débogueurs avec des virgules&#160;:</p> </div> <div class="listingblock"> <div class="content"> <pre><span data-bash-subs="$"></span>DEBUG=app<mark>*</mark> node examples/debug.js app fromages [ 'livarot', 'chaource' ] +0ms app:timer now 1531304027271 +0ms</pre> </div> </div> <div class="listingblock"> <div class="title">debug.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> debug <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'debug'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> log <span class="token operator">=</span> <span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">'app'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(1)</b> <span class="token keyword">const</span> logInterval <span class="token operator">=</span> <span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">'app:timer'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(2)</b> <span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'fromages %o'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'livarot'</span><span class="token punctuation">,</span> <span class="token string">'chaource'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(3)</b> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">logInterval</span><span class="token punctuation">(</span><span class="token string">'now %d'</span><span class="token punctuation">,</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> // <b class="conum">(4)</b> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Création du débogueur <code>app</code>.</p> </li> <li> <p>Création du débogueur <code>app:timer</code>.</p> </li> <li> <p>La fonction de débogage s&#8217;utilise de la même manière que <code>console.log</code>.</p> </li> <li> <p>Cette fonction fait appel au débogueur <code>app:timer</code>.</p> </li> </ol> </div> </div> <div class="sect2"> <h3 id="nodemon">2.2. nodemon</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p><em>nodemon</em> (<span class="URL"><a href="https://npmjs.com/nodemon" class="bare">npmjs.com/nodemon</a></span>) relance le processus actif dès qu&#8217;un fichier ECMAScript ou JSON est modifié. C&#8217;est un module exécutable particulièrement utile lorsque nous voulons prendre en compte les changements dans une application qui tourne en continu. C&#8217;est le cas des applications web, entre autres.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">💬</div> </td> <td class="content"> <div class="paragraph"> <p>Pour en savoir plus, rendez-vous à la section &#8220;<a href="../chapter-07/index.html#dev">Pendant le développement&#160;: relancer le serveur automatiquement</a>&#8221; du <a href="../chapter-07/index.html">chapitre&#160;7</a>.</p> </div> </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="npm_run_all">2.3. npm-run-all</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>npm-run-all</em> (<span class="URL"><a href="https://npmjs.com/npm-run-all" class="bare">npmjs.com/npm-run-all</a></span>) est mon outil favori pour composer avec les scripts&#160;<code>npm</code>. Il a l&#8217;avantage d&#8217;ê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.</p> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-json"><code class="language-json" data-lang="json"><span class="token punctuation">{</span> <span class="token property">"..."</span><span class="token operator">:</span> <span class="token string">"..."</span><span class="token punctuation">,</span> <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"build"</span><span class="token operator">:</span> <span class="token string">"npm-run-all -p 'build:*' -s start"</span><span class="token punctuation">,</span> <span class="token property">"build:css"</span><span class="token operator">:</span> <span class="token string">"sass ..."</span><span class="token punctuation">,</span> <span class="token property">"build:js"</span><span class="token operator">:</span> <span class="token string">"browserify ..."</span><span class="token punctuation">,</span> <span class="token property">"start"</span><span class="token operator">:</span> <span class="token string">"node server.js"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="husky">2.4. husky</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>husky</em> (<span class="URL"><a href="https://npmjs.com/husky" class="bare">npmjs.com/husky</a></span>) intègre Git aux <a href="../chapter-05/index.html#scripts">scripts&#160;<code>npm</code></a>. Autrement dit, vous pouvez déclencher des scripts lors d&#8217;événements Git, lors d&#8217;un <code>push</code>, avant un <code>commit</code> ou après avoir rapatrié des changements.</p> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-json"><code class="language-json" data-lang="json"><span class="token punctuation">{</span> <span class="token property">"..."</span><span class="token operator">:</span> <span class="token string">"..."</span><span class="token punctuation">,</span> <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"precommit"</span><span class="token operator">:</span> <span class="token string">"lint-staged"</span><span class="token punctuation">,</span> <span class="token property">"post-merge"</span><span class="token operator">:</span> <span class="token string">"npm install"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> </div> </div> <div class="paragraph"> <p>La liste complète des <em>hooks</em> Git se trouve dans la documentation officielle&#160;: <span class="URL"><a href="https://git-scm.com/docs/githooks" class="bare">git-scm.com/docs/githooks</a></span>.</p> </div> </div> <div class="sect2"> <h3 id="onchange">2.5. onchange</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>onchange</em> (<span class="URL"><a href="https://npmjs.com/onchange" class="bare">npmjs.com/onchange</a></span>) observe une liste de fichiers en continu et déclenche une commande dès que l&#8217;un d&#8217;entre eux est modifié. C&#8217;est particulièrement utile pour reconstruire automatiquement des fichiers de configuration ou des fichiers <em>front-end</em> pendant le développement.</p> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-json"><code class="language-json" data-lang="json"><span class="token punctuation">{</span> <span class="token property">"..."</span><span class="token operator">:</span> <span class="token string">"..."</span><span class="token punctuation">,</span> <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"build:css"</span><span class="token operator">:</span> <span class="token string">"sass ..."</span><span class="token punctuation">,</span> <span class="token property">"dev"</span><span class="token operator">:</span> <span class="token string">"npm-run-script -p 'watch:*' start"</span><span class="token punctuation">,</span> <span class="token property">"watch:css"</span><span class="token operator">:</span> <span class="token string">"onchange '**/*.scss' -- npm run build:css"</span><span class="token punctuation">,</span> <span class="token property">"start"</span><span class="token operator">:</span> <span class="token string">"node server.js"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="tiny_lr">2.6. tiny-lr</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>tiny-lr</em> (<span class="URL"><a href="https://npmjs.com/tiny-lr" class="bare">npmjs.com/tiny-lr</a></span>) est une implémentation minimale du protocole <em>livereload</em> (<span class="URL"><a href="http://livereload.com" class="bare">livereload.com</a></span>). Il s&#8217;intègre à un serveur HTTP ou à une application <em>Express</em> pour relayer la liste des fichiers modifiés côté client.</p> </div> <div class="paragraph"> <p>Le script ou l&#8217;extension navigateur client remplace les anciens fichiers par les nouveaux pour refléter les changements sans recharger la&#160;page.</p> </div> </div> <div class="sect2"> <h3 id="livereactload">2.7. livereactload</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p><em>livereactload</em> (<span class="URL"><a href="https://npmjs.com/livereactload" class="bare">npmjs.com/livereactload</a></span>) recherche les composants <a href="#react"><em>React</em></a> à chaud, c&#8217;est-à-dire sans rafraîchir la page ni perdre l&#8217;état des données. C&#8217;est un module indispensable pour développer des applications <em>front-end</em