<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ nodejs - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Impara a programmare gratuitamente! Tutorial di programmazione su Python, JavaScript, Linux e molto altro. ]]>
        </description>
        <link>https://www.freecodecamp.org/italian/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ nodejs - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/italian/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 06 May 2026 14:33:03 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/italian/news/tag/nodejs/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Come Installare Node.js su Ubuntu e Aggiornare npm all'Ultima Versione ]]>
                </title>
                <description>
                    <![CDATA[ Se provi ad installare l'ultima versione di node usando il gestore di pacchetti apt finirai con l'avere la versione 10.19.0. Questa è l'ultima versione presente nell'app store ubuntu ma non è l'ultima versione rilasciata da NodeJS. > N.d.T. Le versioni menzionate fanno riferimento al momento della pubblicazione dell'articolo e non ]]>
                </description>
                <link>https://www.freecodecamp.org/italian/news/come-installare-nodejs-su-ubuntu/</link>
                <guid isPermaLink="false">63bd67bf2d9e0906706d62f6</guid>
                
                    <category>
                        <![CDATA[ nodejs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Guido Cusani ]]>
                </dc:creator>
                <pubDate>Fri, 03 Mar 2023 05:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/italian/news/content/images/2023/01/Slice-3-2-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Articolo originale:</strong> <a href="https://www.freecodecamp.org/news/how-to-install-node-js-on-ubuntu-and-update-npm-to-the-latest-version/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Install Node.js on Ubuntu and Update npm to the Latest Version</a>
      </p><p>Se provi ad installare l'ultima versione di node usando il gestore di pacchetti apt finirai con l'avere la versione <strong><strong>10.19.0</strong></strong>. Questa è l'ultima versione presente nell'app store ubuntu ma non è l'ultima versione rilasciata da NodeJS.</p><blockquote>N.d.T.<br>Le versioni menzionate fanno riferimento al momento della pubblicazione dell'articolo e non sono aggiornate.</blockquote><p>Questo succede perché le nuove versioni software rilasciate richiedono mesi prima che il team di Ubuntu le testi e le rilasci nel proprio store ufficiale. Per ottenere l'ultima versione di qualsiasi software dovresti usare pacchetti privati, pubblicati direttamente dagli sviluppatori. </p><p>In questo tutorial, quello che vogliamo è ottenere Node <strong><strong>v12.18.1 </strong></strong>(LTS - con supporto a lungo termine) o <strong><strong>v14.4</strong></strong>. Per ottenere le ultime versioni possiamo usare <strong><strong>nodesource</strong></strong> o <strong><strong>nvm</strong></strong> (node version manager). Ti farò vedere entrambi i modi. </p><p>Tutti i comandi saranno eseguiti utilizzando l'interfaccia a riga di comando (CLI) di Ubuntu.</p><h2 id="usare-nvm-il-mio-metodo-preferito"><strong>Usare<strong> NVM - </strong>il mio metodo preferito</strong></h2><p>Il motivo per cui preferisco nvm è perché permette di muoversi tra diverse versione di node in base al progetto. Capiterà di collaborare a diversi progetti con diverse versioni di node e dunque dover cambiare versione in base a quella richiesta. Per questo nvm è lo strumento migliore. </p><h2 id="installare-nvm"><strong><strong>Install</strong>are<strong> NVM</strong></strong></h2><p><code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash</code></p><p>Per controllare l'effettiva installazione di nvm scrivi nel terminale <code>nvm --version</code>. Se la risposta è qualcosa tipo <code>0.35.3</code> allora sai che è stato installato correttamente.</p><p><strong>Riavvia il tuo terminale per rendere effettivi i cambiamenti.</strong></p><h2 id="installare-nodejs"><strong><strong>Install</strong>are<strong> NodeJS</strong></strong></h2><p>Installiamo NodeJS versione 14.4.</p><p>Semplicemente digita il comando <code>nvm install 14.4.0</code> e fai invio.</p><p>Puoi decidere quale versione installare usando lo stesso comando ma con la versione che desideri. Ad esempio: <code>nvm install 12.18.1</code>.</p><p>Eseguendo il comando verrà installata la versione di NodeJS scelta e automaticamente l'ultima versione di <strong>npm</strong> che potrebbe essere <code>v6.14.5</code>.</p><p>Se desideri spostarti su una versione di node specifica puoi semplicemente usare il comando <code>nvm use &lt;numero-versione&gt;</code>, ad esempio <code>nvm use v12.18.1</code>.</p><p>Per visualizzare la lista delle diverse versioni di node installate con nvm puoi usare il comando <code>nvm ls</code>.</p><h2 id="installare-nodesource"><strong><strong>Install</strong>are<strong> Nodesource</strong></strong></h2><p>Esegui questo comando per dire a Ubuntu che vuoi installare il pacchetto di NodeJS da nodesource. </p><p><code>curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -</code></p><p><strong>N.B.</strong>,<strong> </strong>la versione v14.4.0 è l'ultima versione di Node ma non ha il supporto a lungo termine (LTS). Per installare la versione di Node con LTS cambia il numero della versione da <code>14</code> a <code>12</code> nel comando. </p><p>È probabile ti venga chiesto di inserire password per l'utente root. Scrivila e premi invio. </p><h2 id="installare-nodejs-1"><strong><strong>Install</strong>are<strong> NodeJS</strong></strong></h2><p>Una volta sistemato Nodesource possiamo installare NodeJS v14.4. Esegui <code>sudo apt-get install -y nodejs</code>.</p><p>Una volta fatto, possiamo controllare se effettivamente abbiamo l'ultima versione installata. Possiamo farlo usando il comando <code>nodejs -v</code> che dovrebbe restituire <code>v14.4.0</code>.</p><p>Dovresti avere installato npm in automatico. Per controllare che versione hai puoi usare questo comando: <code>npm version</code>. Se non ottieni un oggetto che include l'ultima versione di npm, o qualcosa di simile a 6.14.5 (<code>{ npm: '6.14.5' }</code>), allora puoi aggiornare manualmente npm con il seguente comando: </p><p><code>npm install -g npm@latest</code>.</p><p>Se dovessero esserci problemi con npm che non può essere aggiornato perché risulta non installato, puoi prima usare il comando <code>sudo apt-get install -y npm</code>, e poi usare il comando precedente per aggiornare. </p><p>Per avviare alcuni pacchetti npm potresti avere bisogno di questo comando: </p><p><code>sudo apt install build-essential</code>.</p><p>E questo è tutto.</p><p>Hai l'ultima versione di NodeJS e NPM sulla tua macchina Ubuntu.</p><p>Buona programmazione:)<br></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Come Aggiornare Node e NPM all'Ultima Versione ]]>
                </title>
                <description>
                    <![CDATA[ Node è un ambiente di runtime che consente agli sviluppatori di eseguire il codice JavaScript al di fuori del browser, nel lato server. NPM, invece, è un gestore di pacchetti per pubblicare pacchetti JavaScript (anche detti moduli Node) nel registro npm [https://www.npmjs.com/]. Puoi anche usarlo per installare pacchetti per le ]]>
                </description>
                <link>https://www.freecodecamp.org/italian/news/aggiornare-node-e-npm/</link>
                <guid isPermaLink="false">63bed6e50a4f0206bd465650</guid>
                
                    <category>
                        <![CDATA[ nodejs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Dario Di Cillo ]]>
                </dc:creator>
                <pubDate>Wed, 18 Jan 2023 05:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/italian/news/content/images/2023/01/update.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Articolo originale:</strong> <a href="https://www.freecodecamp.org/news/how-to-update-node-and-npm-to-the-latest-version/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Update Node and NPM to the Latest Version</a>
      </p><p>Node è un ambiente di runtime che consente agli sviluppatori di eseguire il codice JavaScript al di fuori del browser, nel lato server.</p><p>NPM, invece, è un gestore di pacchetti per pubblicare pacchetti JavaScript (anche detti moduli Node) nel <a href="https://www.npmjs.com/">registro npm</a>. Puoi anche usarlo per installare pacchetti per le tue applicazioni.</p><p>Per installare Node, devi andare sul sito di <a href="https://nodejs.org/en/">Nodejs</a> e scaricare l'installer. Dopo il download, esegui l'installer e segui i passaggi, accetta i termini di utilizzo e aspetta che l'installazione sia terminata.</p><p>Quando installi Node, ottieni anche la CLI <code>npm</code> che puoi usare per gestire i pacchetti nelle tua applicazioni.</p><p>Tuttavia, Node e NPM possono essere aggiornati separatamente alle loro ultime versioni, e nel resto di questo articolo ti mostrerò come.</p><h2 id="come-aggiornare-node"><strong>Come aggiornare Node</strong></h2><h3 id="1-usa-npm-per-aggiornare-la-versione-di-node"><strong>1. Usa NPM per aggiornare la versione di Node</strong></h3><p>Per aggiornare Node con NPM, installa il pacchetto <a href="https://www.npmjs.com/package/n">n</a>, che servirà per gestire in modo interattivo le versioni di node sul tuo dispositivo.</p><p>Ecco i passaggi:</p><h4 id="pulisci-la-cache-di-npm"><strong>Pulisci la cache di NPM</strong></h4><p>Quando installi le dipendenze, alcuni moduli vengono memorizzati nella cache per migliorare la velocità dell'installazione per i download successivi. Quindi, prima di tutto, pulisci la cache di NPM.</p><h4 id="installa-n"><strong>Installa n</strong></h4><pre><code class="language-shell">npm install -g n
</code></pre><p>Ti occorrerà installare questo pacchetto globalmente dato che gestisce alla radice le versioni di Node.</p><h4 id="installa-una-nuova-versione-di-node"><strong>Installa una nuova versione di Node</strong></h4><pre><code class="language-shell">n lts
n latest
</code></pre><p>I due comandi qui sopra installano l'ultima versione di Node con supporto a lungo termine.</p><h4 id="rimuovi-le-versioni-precedentemente-installate"><strong>Rimuovi le versioni precedentemente installate</strong></h4><pre><code class="language-shell">n prune
</code></pre><p>Questo comando rimuove le versioni precedentemente installate salvate nella cache mantenendo soltanto l'ultima versione.</p><h3 id="2-usa-nvm-per-aggiornare-la-versione-di-node"><strong>2. Usa NVM per aggiornare la versione di Node</strong></h3><p>NVM sta per Node Version Manager (gestore di versione di Node) e, come suggerisce il nome, aiuta la gestione delle versioni di Node. Con NVM puoi installare delle versioni di Node e specificare la versione da utilizzare in un progetto.</p><p>NVM rende semplice testare dei progetti con diverse versioni di Node.</p><p>Per aggiornare la versione di Node con NVM, devi prima installare NVM.</p><p>Ecco la <a href="https://github.com/nvm-sh/nvm#installing-and-updating">guida di installlazione</a>.</p><p>Una volta terminata l'installazione, puoi installare i pacchetti con:</p><pre><code class="language-shell">nvm install [versione]
</code></pre><p>Puoi installare l'ultima versione con:</p><pre><code class="language-shell">nvm install node
</code></pre><p>E disinstallare le altre versioni con:</p><pre><code class="language-shell">nvm uninstall [versione]
</code></pre><p>Con molte versioni installate, potresti aver bisogno di specificare la versione da utilizzare in un determinato momento. Un modo per farlo è impostare un alias predefinito, così:</p><pre><code class="language-shell">nvm alias default [versione]
</code></pre><p>In questo modo, verrà eseguita la versione di Node specificata.</p><h3 id="3-scarica-node-dal-sito"><strong>3. Scarica Node dal sito</strong></h3><p>Puoi anche ottenere l'ultima versione direttamente dal sito di <a href="https://nodejs.org/en/">Node.js</a>, dove puoi trovare l'ultima versione e le versioni con supporto a lungo termine per il tuo dispositivo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-7.png" class="kg-image" alt="image-7" width="600" height="400" loading="lazy"><figcaption>Pagina di download di Node.js</figcaption></figure><p>Scaricando l'ultima versione ottieni anche l'ultima versione di NPM.</p><h2 id="come-aggiornare-npm"><strong>Come aggiornare NPM</strong></h2><p>Proprio come usi NPM per aggiornare pacchetti, puoi usarlo anche per aggiornare sé stesso. Ecco il comando per farlo:</p><pre><code class="language-shell">npm install -g npm@latest
</code></pre><p>Questo comando installerà l'ultima versione di NPM globalmente.</p><p>Su Mac, potresti dover usare il comando <code>sudo</code> prima di NPM, dato che installa NPM nella radice del tuo dispositivo e per farlo ti occorrono privilegi.</p><h2 id="conclusione"><strong>Conclusione</strong></h2><p>In questo articolo, abbiamo visto come aggiornare Node e NPM all'ultima versione.</p><p>Ricapitolando, quando installi Node, ottieni automaticamente anche NPM. E ottieni NPM anche se aggiorni Node tramite il download dal sito web.</p><p>Infine abbiamo anche visto come aggiornare Node e NPM globalmente sul tuo dispositivo.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Richiedere i moduli in Node.js: tutto ciò che devi sapere ]]>
                </title>
                <description>
                    <![CDATA[ > Aggiornamento: questo articolo fa ora parte del mio libro "Node.js Beyond The Basics". Leggi la versione aggiornata di questo contenuto e altro su Node su  jscomplete.com/node-beyond-basics [https://jscomplete.com/g/node-modules] . Node utilizza due moduli principali per la gestione delle dipendenze dei moduli:  * Il modulorequire, che è disponibile nell'ambito ]]>
                </description>
                <link>https://www.freecodecamp.org/italian/news/richiedere-moduli-in-node-js-tutto-cio-che-devi-sapere/</link>
                <guid isPermaLink="false">62057172b45ad1050e27f726</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ NODE ]]>
                    </category>
                
                    <category>
                        <![CDATA[ nodejs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Angelo Mirabelli ]]>
                </dc:creator>
                <pubDate>Wed, 16 Feb 2022 09:29:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/italian/news/content/images/2022/02/1_AL0-iuggGnBLSvSVvt0Xzw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Articolo originale:</strong> <a href="https://www.freecodecamp.org/news/requiring-modules-in-node-js-everything-you-need-to-know-e7fbd119be8/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Requiring modules in Node.js: Everything you need to know</a>
      </p><blockquote><strong><strong>Aggiornamento:</strong></strong> questo articolo fa ora parte del mio libro "Node.js Beyond The Basics".<br><br>Leggi la versione aggiornata di questo contenuto e altro su Node su <a href="https://jscomplete.com/g/node-modules" rel="noopener"><strong><strong>jscomplete.com/node-beyond-basics</strong></strong></a> .</blockquote><p>Node utilizza due moduli principali per la gestione delle dipendenze dei moduli:</p><ul><li>Il modulo<code>require</code>, che è disponibile nell'ambito globale, quindi non è necessario richiede <code>require('require')</code>.</li><li>Il modulo <code>module</code>, che è anche disponibile nell'ambito globale, e non è necessario richiedere <code>require('module')</code>.</li></ul><p>Puoi pensare al modulo <code>require</code> come al comando e al modulo <code>module</code> come al raccoglitore di tutti i moduli richiesti.</p><p>Richiedere un modulo in Node non è un concetto così complicato.</p><pre><code class="language-js">const config = require('/path/to/file');</code></pre><p>L'oggetto principale esportato dal modulo <code>require</code> è una funzione (come nell'esempio precedente). Quando richiama quella funzione <code>require()</code> con un percorso di file locale come unico argomento della funzione, Node esegue la seguente sequenza di passaggi:</p><ul><li><strong><strong>Risoluzione</strong></strong> : per trovare il percorso assoluto del file.</li><li><strong><strong>Caricamento</strong></strong> : per determinare il tipo di contenuto del file.</li><li><strong><strong>Wrapping</strong></strong> : per assegnare al file il suo ambito privato. Questo è ciò che rende gli oggetti <code>require</code> e <code>module</code> locali in ogni file di cui abbiamo bisogno.</li><li><strong><strong>Valutazione</strong></strong> : questo è ciò che la VM alla fine fa con il codice caricato.</li><li><strong><strong>Memorizzazione nella cache</strong></strong> : in modo che quando richiediamo nuovamente questo file, non ripercorriamo tutti i passaggi un'altra volta.</li></ul><p>In questo articolo, cercherò di spiegare con esempi, queste diverse fasi e come influiscono sul modo in cui scriviamo i moduli in Node.</p><p>Fammi prima creare una directory per ospitare tutti gli esempi usando il mio terminale:</p><pre><code class="language-bash">mkdir ~/learn-node &amp;&amp; cd ~/learn-node</code></pre><p>Tutti i comandi nel resto di questo articolo verranno eseguiti dall'interno di <code>~/learn-node</code>.</p><h4 id="risoluzione-di-un-percorso-locale"><strong>Risoluzione di un percorso locale</strong></h4><p>Lascia che ti presenti l'oggetto <code>module</code>. Puoi verificarlo in una semplice sessione REPL:</p><pre><code class="language-bash">~/learn-node $ node
&gt; module
Module {
  id: '&lt;repl&gt;',
  exports: {},
  parent: undefined,
  filename: null,
  loaded: false,
  children: [],
  paths: [ ... ] }</code></pre><p>Ogni oggetto modulo ottiene una proprietà <code>id</code> per identificarlo. Questo <code>id</code> è solitamente il percorso completo del file, ma in una sessione REPL è semplicemente<code>&lt;repl&gt;.</code></p><p>I moduli del nodo hanno una relazione uno-a-uno con i file sul file system. Richiediamo un modulo caricando il contenuto di un file in memoria.</p><p>Tuttavia, poiché Node permette molti modi di richiedere un file (ad esempio, con un percorso relativo o un percorso preconfigurato), prima di poter caricare il contenuto di un file nella memoria, dobbiamo trovare la posizione assoluta di quel file.</p><p>Quando richiediamo un modulo <code>'find-me'</code>, senza specificare un percorso:</p><pre><code class="language-js">require('find-me');</code></pre><p>Il nodo cercherà <code>find-me.js</code> in tutti i percorsi specificati da <code>module.paths</code>— in ordine.</p><pre><code class="language-bash">~/learn-node $ node
&gt; module.paths
[ '/Users/samer/learn-node/repl/node_modules',
  '/Users/samer/learn-node/node_modules',
  '/Users/samer/node_modules',
  '/Users/node_modules',
  '/node_modules',
  '/Users/samer/.node_modules',
  '/Users/samer/.node_libraries',
  '/usr/local/Cellar/node/7.7.1/lib/node' ]</code></pre><p>L'elenco dei percorsi è fondamentalmente un elenco di directory di node_modules, dalla directory corrente alla directory principale. Include anche alcune directory legacy il cui utilizzo non è raccomandato.</p><p>Se Node non riesce a trovare <code>find-me.js</code> in nessuno di questi percorsi, genererà un "cannot find module error".</p><pre><code class="language-bash">~/learn-node $ node
&gt; require('find-me')
Error: Cannot find module 'find-me'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at repl:1:1
    at ContextifyScript.Script.runInThisContext (vm.js:23:33)
    at REPLServer.defaultEval (repl.js:336:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.onLine (repl.js:533:10)</code></pre><p>Se ora crei una directory locale <code>node_modules</code> e inserisci un file <code>find-me.js</code> lì, la riga <code>require('find-me')</code> la troverà.</p><pre><code class="language-bash">~/learn-node $ mkdir node_modules 

~/learn-node $ echo "console.log('Non mi sono perso');" &gt; node_modules/find-me.js

~/learn-node $ node
&gt; require('find-me');
Non mi sono perso
{}
&gt;</code></pre><p>Se esistesse un altro file <code>find-me.js</code> in uno qualsiasi degli altri percorsi, ad esempio, se avessimo una directory <code>node_modules</code> nella directory home e avessimo un diverso file <code>find-me.js</code> in quella cartella:</p><pre><code class="language-bash">$ mkdir ~/node_modules
$ echo "console.log('Io sono la radice di tutti i problemi');" &gt; ~/node_modules/find-me.js</code></pre><p>Quando eseguiamo <code>require('find-me')</code> nella directory <code>learn-node</code>, che ha il suo <code>node_modules/find-me.js</code>, il file <code>find-me.js</code> nella directory home non verrà caricato affatto:</p><pre><code class="language-bash">~/learn-node $ node
&gt; require('find-me')
Non mi sono perso
{}
&gt;</code></pre><p>Se rimuoviamo la directory locale <code>node_modules</code> in <code>~/learn-node</code> e proviamo a richiede <code>find-me</code> ancora una volta, verrà utilizzato il file nella directory home <code>node_modules</code> :</p><pre><code class="language-bash">~/learn-node $ rm -r node_modules/
~/learn-node $ node
&gt; require('find-me')
Io sono la radice di tutti i problemi
{}
&gt;</code></pre><h4 id="richiedere-una-cartella"><strong>Richiedere una cartella</strong></h4><p>I moduli possono non essere file. Possiamo anche creare una cartella <code>find-me</code> sotto <code>node_modules</code> e inserire lì un file <code>index.js</code>. La stessa riga <code>require('find-me')</code> utilizzerà il file <code>index.js</code> di quella cartella:</p><pre><code class="language-bash">~/learn-node $ mkdir -p node_modules/find-me

~/learn-node $ echo "console.log('Ritrovato.');" &gt; node_modules/find-me/index.js

~/learn-node $ node
&gt; require('find-me');
Ritrovato.
{}
&gt;</code></pre><p>Nota come ha ancora ignorato il percorso della home directory <code>node_modules</code> poiché ne abbiamo una locale.</p><p>Un file <code>index.js</code> verrà utilizzato per impostazione predefinita quando richiediamo una cartella, ma possiamo indicare con quale file iniziare nella cartella utilizzando la proprietà <code>main</code> in <code>package.json</code>. Ad esempio, per fare in modo che la riga <code>require('find-me')</code> si risolva in un file diverso nella cartella <code>find-me</code>, tutto ciò che dobbiamo fare è aggiungere lì un file <code>package.json</code> e specificare quale file deve essere usato per risolvere questa cartella:</p><pre><code class="language-bash">~/learn-node $ echo "console.log('I rule');" &gt; node_modules/find-me/start.js

~/learn-node $ echo '{ "name": "find-me-folder", "main": "start.js" }' &gt; node_modules/find-me/package.json

~/learn-node $ node
&gt; require('find-me');
I rule
{}
&gt;</code></pre><h4 id="require-resolve"><strong>require.resolve</strong></h4><p>Se vuoi solo risolvere il modulo e non eseguirlo, puoi usare la funzione <code>require.resolve</code> . Questa si comporta esattamente come la funzione principale <code>require</code> , ma non carica il file. Verrà comunque generato un errore se il file non esiste e restituirà il percorso completo del file una volta trovato.</p><pre><code class="language-bash">&gt; require.resolve('find-me');
'/Users/samer/learn-node/node_modules/find-me/start.js'
&gt; require.resolve('not-there');
Error: Cannot find module 'not-there'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.resolve (internal/module.js:27:19)
    at repl:1:9
    at ContextifyScript.Script.runInThisContext (vm.js:23:33)
    at REPLServer.defaultEval (repl.js:336:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.onLine (repl.js:533:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:191:7)
&gt;</code></pre><p>Questo può essere utilizzato, ad esempio, per verificare se un pacchetto opzionale è installato o meno e utilizzarlo solo quando è disponibile.</p><h4 id="percorsi-relativi-e-assoluti"><strong>Percorsi relativi e assoluti</strong></h4><p>Oltre a risolvere i moduli dall'interno delle directory <code>node_modules</code>, possiamo anche posizionare il modulo dove vogliamo e richiederlo con percorsi relativi ( <code>./</code>e <code>../</code>) o con percorsi assoluti che iniziano con <code>/</code>.</p><p>Se, ad esempio, il file <code>find-me.js</code> era in una cartella <code>lib</code> anziché in una cartella <code>node_modules</code>, possiamo richiederlo con:</p><pre><code class="language-js">require('./lib/find-me');</code></pre><h4 id="relazione-genitore-figlio-tra-file"><strong>Relazione genitore-figlio tra file</strong></h4><p>Crea un file <code>lib/util.js</code> e aggiungi una riga <code>console.log</code> per identificarlo. Inoltre, stampa con <code>console.log</code> l'oggetto stesso <code>module</code>:</p><pre><code class="language-bash">~/learn-node $ mkdir lib
~/learn-node $ echo "console.log('In util', module);" &gt; lib/util.js</code></pre><p>Fai lo stesso per un file <code>index.js</code>, che è ciò che eseguiremo con il comando node. Fai in modo che questo file <code>index.js</code> richieda <code>lib/util.js</code>:</p><pre><code class="language-bash">~/learn-node $ echo "console.log('In index', module); require('./lib/util');" &gt; index.js</code></pre><p>Ora esegui il file <code>index.js</code> con node:</p><pre><code class="language-bash">~/learn-node $ node index.js
In index Module {
  id: '.',
  exports: {},
  parent: null,
  filename: '/Users/samer/learn-node/index.js',
  loaded: false,
  children: [],
  paths: [ ... ] }
In util Module {
  id: '/Users/samer/learn-node/lib/util.js',
  exports: {},
  parent:
   Module {
     id: '.',
     exports: {},
     parent: null,
     filename: '/Users/samer/learn-node/index.js',
     loaded: false,
     children: [ [Circular] ],
     paths: [...] },
  filename: '/Users/samer/learn-node/lib/util.js',
  loaded: false,
  children: [],
  paths: [...] }</code></pre><p>Nota come il modulo principale <code>index</code> <code>(id: '.')</code> sia ora elencato come genitore per il modulo <code>lib/util</code>. Tuttavia, il modulo <code>lib/util</code> non è stato elencato come figlio del modulo <code>index</code>. Invece, abbiamo lì il valore <code>[Circular]</code> perché questo è un riferimento circolare. Se Node stampa l'oggetto modulo <code>lib/util</code>, entrerà in un ciclo infinito. Ecco perché sostituisce semplicemente il riferimento <code>lib/util</code> con <code>[Circular]</code>.</p><p>Cosa ancora più importante ora, cosa succede se il modulo <code>lib/util</code> richiede il modulo principale <code>index</code>? È qui che entriamo in quella che è nota come la dipendenza modulare circolare, consentita in Node.</p><p>Per capirlo meglio, comprendiamo prima alcuni altri concetti sull'oggetto <em>module</em>.</p><h4 id="exports-module-exports-e-caricamento-sincrono-dei-moduli"><strong>exports, module.exports e caricamento sincrono dei moduli</strong></h4><p>In ogni modulo, <em>exports</em> è un oggetto speciale. Se hai notato sopra, ogni volta che abbiamo stampato un oggetto <em>module</em>, aveva una proprietà exports che è stata finora un oggetto vuoto. Possiamo aggiungere qualsiasi attributo a questo speciale oggetto di esportazione . Ad esempio, esportiamo un attributo <em>id</em> per <code>index.js</code> e <code>lib/util.js</code>:</p><pre><code class="language-js">// Aggiungi la riga seguente in cima a lib/util.js
exports.id = 'lib/util';

// Aggiungi la riga seguente in cima a index.js
exports.id = 'index';</code></pre><p>Quando ora eseguiamo <code>index.js</code>, vedremo questi attributi come gestiti sull'oggetto <code>module</code> di ogni file:</p><pre><code class="language-bash">~/learn-node $ node index.js
In index Module {
  id: '.',
  exports: { id: 'index' },
  loaded: false,
  ... }
In util Module {
  id: '/Users/samer/learn-node/lib/util.js',
  exports: { id: 'lib/util' },
  parent:
   Module {
     id: '.',
     exports: { id: 'index' },
     loaded: false,
     ... },
  loaded: false,
  ... }</code></pre><p>Ho rimosso alcuni attributi nell'output sopra per mantenerlo breve, ma nota come l'oggetto <code>exports</code> ora ha gli attributi che abbiamo definito in ciascun modulo. Puoi inserire tutti gli attributi che vuoi su quell'oggetto <em>exports</em> e puoi effettivamente cambiare l'intero oggetto in qualcos'altro. Ad esempio, per modificare l'oggetto <em>exports</em> in modo che sia una funzione anziché un oggetto, procediamo come segue:</p><pre><code class="language-js">// Aggiungi la riga seguente index.js prima di console.log

module.exports = function() {};</code></pre><p>Ora quando esegui <code>index.js</code>, vedrai come l'oggetto <code>exports</code> sia una funzione:</p><pre><code class="language-bash">~/learn-node $ node index.js
In index Module {
  id: '.',
  exports: [Function],
  loaded: false,
  ... }</code></pre><p>Nota come non abbiamo fatto <code>exports = function() {}</code>per trasformare l'oggetto <code>exports</code> in una funzione. In realtà non possiamo farlo perché la variabile <code>exports</code> all'interno di ogni modulo è solo un riferimento a <code>module.exports</code> che gestisce le proprietà esportate. Quando riassegnamo la variabile <code>exports</code>, quel riferimento viene perso e introdurremmo una nuova variabile invece di cambiare l'oggetto <code>module.exports</code>.</p><p>L'oggetto <code>module.exports</code> in ogni modulo è ciò che la funzione <code>require</code> restituisce quando richiediamo quel modulo. Ad esempio, cambia la riga <code>require('./lib/util')</code> in <code>index.js</code>:</p><pre><code class="language-js">const UTIL = require('./lib/util');

console.log('UTIL:', UTIL);</code></pre><p>Questo catturerà le proprietà esportate in <code>lib/util</code> nella costante <code>UTIL</code>. Ora quando eseguiamo <code>index.js</code>, l'ultima riga produrrà:</p><pre><code class="language-bash">UTIL: { id: 'lib/util' }</code></pre><p>Parliamo anche dell'attributo <code>loaded</code> di ogni modulo. Finora, ogni volta che abbiamo stampato un oggetto <em>module</em>, abbiamo visto un attributo <code>loaded</code> in quell'oggetto con un valore <code>false</code>.</p><p>Il modulo <code>module</code> utilizza l'attributo <code>loaded</code> per tenere traccia di quali moduli sono stati caricati (valore <code>true</code>) e quali moduli sono ancora in fase di caricamento (valore <code>false</code>). Possiamo, ad esempio, vedere il modulo <code>index.js</code> completamente caricato se stampiamo il suo oggetto <code>module</code> nel ciclo successivo nel ciclo di eventi utilizzando una chiamata <code>setImmediate</code>:</p><pre><code>// In index.js
setImmediate(() =&gt; {
  console.log('Oggetto del modulo index.js è ora caricato!', module)
});</code></pre><p>L'output sarebbe:</p><pre><code class="language-bash">Oggetto del modulo index.js è ora caricato! Module {
  id: '.',
  exports: [Function],
  parent: null,
  filename: '/Users/samer/learn-node/index.js',
  loaded: true,
  children:
   [ Module {
       id: '/Users/samer/learn-node/lib/util.js',
       exports: [Object],
       parent: [Circular],
       filename: '/Users/samer/learn-node/lib/util.js',
       loaded: true,
       children: [],
       paths: [Object] } ],
  paths:
   [ '/Users/samer/learn-node/node_modules',
     '/Users/samer/node_modules',
     '/Users/node_modules',
     '/node_modules' ] }</code></pre><p>Nota come in questo output ritardato di <code>console.log</code> sia <code>lib/util.js</code> che <code>index.js</code> sono completamente caricati.</p><p>L'oggetto <code>exports</code> diventa completo quando Node termina il caricamento del modulo (e lo etichetta così). L'intero processo di richiesta/caricamento di un modulo è <em><em>sincrono. </em></em>Ecco perché siamo stati in grado di vedere i moduli completamente caricati dopo un ciclo nel ciclo degli eventi.</p><p>Ciò significa anche che non possiamo modificare l'oggetto <code>exports</code> in modo asincrono. Non possiamo, ad esempio, fare quanto segue in nessun modulo:</p><pre><code class="language-js">fs.readFile('/etc/passwd', (err, data) =&gt; {
  if (err) throw err;
  
  exports.data = data; // Non funzionerà.
});</code></pre><h4 id="dipendenza-del-modulo-circolare"><strong>Dipendenza del modulo circolare</strong></h4><p>Proviamo ora a rispondere all'importante domanda sulla dipendenza circolare in Node: cosa succede quando il modulo 1 richiede il modulo 2 e il modulo 2 richiede il modulo 1?</p><p>Per scoprirlo, creiamo i seguenti due file in <code>lib/</code>, <code>module1.js</code> e <code>module2.js</code> e facciamo in modo che si richiedano a vicenda:</p><pre><code class="language-js">// lib/module1.js

exports.a = 1;

require('./module2');

exports.b = 2;
exports.c = 3;

// lib/module2.js

const Module1 = require('./module1');
console.log('Module1 è parzialmente caricato qui', Module1);</code></pre><p>Quando eseguiamo <code>module1.js</code> si vedrà quanto segue:</p><pre><code class="language-bash">~/learn-node $ node lib/module1.js
Module1 è parzialmente caricato qui { a: 1 }</code></pre><p>Abbiamo richiesto <code>module2</code> prima che <code>module1</code> fosse completamente caricato e poiché <code>module2</code> ha richiesto <code>module1</code> prima del suo completo caricamento, ciò che otteniamo dall'oggetto <code>exports</code> a quel punto sono tutte le proprietà esportate prima della dipendenza circolare. Solo la proprietà <code>a</code> è stata riportata perché sia <code>b</code> che <code>c</code> sono stati esportati dopo aver richiesto <code>module2</code> e stampato <code>module1</code>.</p><p>Node rende ciò davvero semplice. Durante il caricamento di un modulo, costruisce l'oggetto <code>exports</code>. Puoi richiedere il modulo prima che il caricamento sia terminato e otterrai solo un oggetto <em>exports</em> parziale con tutto ciò che è stato definito sino a quel momento.</p><h4 id="componenti-aggiuntivi-json-e-c-c-"><strong>Componenti aggiuntivi JSON e C/C++</strong></h4><p>Possiamo richiedere in modo nativo file JSON e file aggiuntivi C++ con la funzione <code>require</code>. Non è nemmeno necessario specificare un'estensione di file per farlo.</p><p>Se non è stata specificata un'estensione di file, la prima cosa che Node tenterà di risolvere è un file <code>.js</code>. Se non riesce a trovare un file <code>.js</code>, proverà un file <code>.json</code> e lo analizzerà se trovato come file di testo JSON. Successivamente, proverà a trovare un file binario <code>.node</code>. Tuttavia, per rimuovere l'ambiguità, sarebbe meglio specificare un'estensione di file quando richiedi qualcosa di diverso dai file <code>.js</code>.</p><p>La richiesta di file JSON è utile se, ad esempio, tutto ciò che devi gestire in quel file sono alcuni valori di configurazione statici o alcuni valori che leggi periodicamente da un'origine esterna. Ad esempio, se avessimo il seguente file <code>config.json</code>:</p><pre><code class="language-json">{
  "host": "localhost",
  "port": 8080
}</code></pre><p>Possiamo richiederlo direttamente in questo modo:</p><pre><code>const { host, port } = require('./config');

console.log(`Il server verrà eseguito a http://${host}:${port}`);</code></pre><p>L'esecuzione del codice sopra avrà questo output:</p><pre><code class="language-bash">Il server verrà eseguito a http://localhost:8080</code></pre><p>Se Node non riesce a trovare un file <code>.js</code> o un file <code>.json</code>, cercherà un file <code>.node</code> e interpreterà il file come un modulo aggiuntivo compilato.</p><p>Il sito della documentazione di Node ha un <a href="https://nodejs.org/api/addons.html#addons_hello_world" rel="noopener">file aggiuntivo di esempio</a> scritto in C++. È un modulo semplice che espone una funzione <code>hello()</code> che stampa "hello world".</p><p>È possibile utilizzare il pacchetto <code>node-gyp</code> per compilare e creare il file <code>.cc</code> in un file <code>.node</code>. Devi solo configurare un file <a href="https://nodejs.org/api/addons.html#addons_building" rel="noopener">binding.gyp</a> per dire a <code>node-gyp</code> cosa fare.</p><p>Una volta che hai il file <code>addon.node</code> (o qualunque nome tu specifichi in <code>binding.gyp</code>), puoi richiederlo in modo nativo proprio come qualsiasi altro modulo:</p><pre><code class="language-js">const addon = require('./addon');

console.log(addon.hello());</code></pre><p>Possiamo effettivamente vedere il supporto delle tre estensioni guardando <code>require.extensions</code>.</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/D3NuN7cetXAjYpHfqBGribFo-ex0fj-AvuDA" class="kg-image" alt="D3NuN7cetXAjYpHfqBGribFo-ex0fj-AvuDA" width="800" height="443" loading="lazy"></figure><p>Osservando le funzioni per ciascuna estensione, puoi vedere chiaramente cosa farà Node con ciascuna. Esso utilizza <code>module._compile</code> per i file <code>.js</code>, <code>JSON.parse</code> per i file <code>.json</code> e <code>process.dlopen</code> per i file <code>.node</code>.</p><h4 id="tutto-il-codice-che-scrivi-in-node-sar-racchiuso-in-funzioni"><strong>Tutto il codice che scrivi in ​​Node sarà racchiuso in funzioni</strong></h4><p>Il wrapping dei moduli da parte di Node è spesso frainteso. Per capirlo, lascia che ti ricordi la relazione <code>exports</code>/ <code>module.exports</code>.</p><p>Possiamo usare l'oggetto <code>exports</code> per esportare le proprietà, ma non possiamo sostituire l'oggetto <code>exports</code> direttamente perché è solo un riferimento a <code>module.exports</code></p><pre><code class="language-js">exports.id = 42; // Questo è ok.

exports = { id: 42 }; // Questo non va bene.

module.exports = { id: 42 }; // Questo è ok.</code></pre><p>In che modo esattamente questo oggetto <code>exports</code>, che sembra essere globale per ogni modulo, viene definito come riferimento sull'oggetto <code>module</code> ?</p><p>Consentitemi di porre un'altra domanda prima di spiegare il processo di wrapping di Node.</p><p>In un browser, quando dichiariamo una variabile in uno script come questo:</p><pre><code>var answer = 42;</code></pre><p>Quella variabile <code>answer</code> sarà globalmente disponibile in tutti gli script dopo lo script che l'ha definita.</p><p>Questo non è il caso di Node. Quando definiamo una variabile in un modulo, gli altri moduli del programma non avranno accesso a quella variabile. Quindi, come mai le variabili in Node hanno magicamente un ambito globale?</p><p>La risposta è semplice. Prima di compilare un modulo, Node racchiude il codice del modulo stesso in una funzione, che possiamo ispezionare usando la proprietà <code>wrapper</code> del modulo <code>module</code>.</p><pre><code class="language-bash">~ $ node
&gt; require('module').wrapper
[ '(function (exports, require, module, __filename, __dirname) { ',
  '\n});' ]
&gt;</code></pre><p>Node non esegue direttamente il codice che scrivi in ​​un file. Esegue questa funzione wrapper che avrà il tuo codice nel suo corpo. Questo è ciò che mantiene le variabili di primo livello, che sono definite in qualsiasi modulo con ambito a questo modulo.</p><p>Questa funzione wrapper ha 5 argomenti: <code>exports</code>, <code>require</code>, <code>module</code>, <code>__filename</code> e <code>__dirname</code>. Questo è ciò che li fa sembrare globali quando in realtà sono specifici per ciascun modulo.</p><p>Tutti questi argomenti ottengono i loro valori quando Node esegue la funzione wrapper. <code>exports</code> è definito come un riferimento a <code>module.exports</code> prima di quello. <code>require</code> e <code>module</code> sono entrambi specifici della funzione da eseguire, e le variabili <code>__filename</code>/ <code>__dirname</code> conterranno il nome assoluto del file del modulo wrapped e il percorso della directory.</p><p>Puoi vedere questo wrapping in azione se esegui uno script con un problema sulla prima riga:</p><pre><code class="language-bash">~/learn-node $ echo "euaohseu" &gt; bad.js

~/learn-node $ node bad.js
~/bad.js:1
(function (exports, require, module, __filename, __dirname) { euaohseu
                                                              ^
ReferenceError: euaohseu is not defined</code></pre><p>Nota come la prima riga dello script riportato sopra, fosse la funzione wrapper, non il riferimento errato.</p><p>Inoltre, poiché ogni modulo viene racchiuso in una funzione, possiamo effettivamente accedere agli argomenti di quella funzione con la parola chiave <code>arguments</code>:</p><pre><code class="language-bash">~/learn-node $ echo "console.log(arguments)" &gt; index.js

~/learn-node $ node index.js
{ '0': {},
  '1':
   { [Function: require]
     resolve: [Function: resolve],
     main:
      Module {
        id: '.',
        exports: {},
        parent: null,
        filename: '/Users/samer/index.js',
        loaded: false,
        children: [],
        paths: [Object] },
     extensions: { ... },
     cache: { '/Users/samer/index.js': [Object] } },
  '2':
   Module {
     id: '.',
     exports: {},
     parent: null,
     filename: '/Users/samer/index.js',
     loaded: false,
     children: [],
     paths: [ ... ] },
  '3': '/Users/samer/index.js',
  '4': '/Users/samer' }</code></pre><p>Il primo argomento è l'oggetto <code>exports</code>, che inizialmente è vuoto. Quindi abbiamo gli oggetti <code>require</code>/ <code>module</code>, entrambi istanze associate al file <code>index.js</code> che stiamo eseguendo. Non sono variabili globali. Gli ultimi 2 argomenti sono il percorso del file e il percorso della sua directory.</p><p>Il valore restituito dalla funzione di wrapping è <code>module.exports</code>. All'interno della funzione wrapped, possiamo utilizzare l'oggetto <code>exports</code> per modificare le proprietà di <code>module.exports</code>, ma non possiamo riassegnare <em>exports</em> perché è solo un riferimento.</p><p>Quello che succede è più o meno equivalente a:</p><pre><code class="language-js">function (require, module, __filename, __dirname) {
  let exports = module.exports;
  
  // Il tuo codice...
  
  return module.exports;
}</code></pre><p>Se cambiassimo l'intero oggetto <code>exports</code>, non sarebbe più un riferimento a <code>module.exports</code>. Questo è il modo in cui la referenziazione degli oggetti di JavaScript funziona ovunque, non solo in questo contesto.</p><h4 id="l-oggetto-require"><strong>L'oggetto require</strong></h4><p>Non c'è niente di speciale in <code>require</code>. È un oggetto che agisce principalmente come una funzione che prende il nome di modulo o un percorso e restituisce l'oggetto <code>module.exports</code>. Possiamo semplicemente sovrascrivere l'oggetto <code>require</code> con la nostra logica, se vogliamo.</p><p>Ad esempio, a solo scopo di test, vogliamo che ogni chiamata <code>require</code> venga ingannata per impostazione predefinita e restituisca semplicemente un oggetto falso invece dell'oggetto di esportazione del modulo richiesto. Questa semplice riassegnazione di require farà il trucco:</p><pre><code class="language-js">require = function() {

  return { mocked: true };
  
}</code></pre><p>Dopo aver eseguito la suddetta riassegnazione di <code>require</code>, ogni chiamata <code>require('something')</code> nello script restituirà semplicemente l'oggetto che abbiamo definito.</p><p>L'oggetto require ha anche proprietà proprie. Abbiamo visto la proprietà <code>resolve</code>, che è una funzione che esegue solo la fase di risoluzione del processo require. Sopra abbiamo visto anche <code>require.extensions</code>.</p><p>C'è anche <code>require.main</code> che può essere utile per determinare se lo script è richiesto o eseguito direttamente.</p><p>Supponiamo, ad esempio, di avere questa semplice funzione <code>printInFrame</code> in <code>print-in-frame.js</code>:</p><pre><code class="language-js">// In print-in-frame.js

const printInFrame = (size, header) =&gt; {
  console.log('*'.repeat(size));
  console.log(header);
  console.log('*'.repeat(size));
};</code></pre><p>La funzione accetta un argomento numerico <code>size</code> e un argomento stringa <code>header</code> e stampa quell'intestazione in una cornice di stelle con la dimensione specificata.</p><p>Vogliamo usare questo file in due modi:</p><ol><li>Direttamente dalla riga di comando in questo modo:</li></ol><pre><code class="language-bash">~/learn-node $ node print-in-frame 8 Hello</code></pre><p>Passando 8 e Hello come argomenti della riga di comando per stampare "Hello" in una cornice di 8 stelle.</p><p>2. Con <code>require</code>. Supponendo che il modulo richiesto esporterà la funzione <code>printInFrame</code>, possiamo semplicemente chiamarla:</p><pre><code>const print = require('./print-in-frame');

print(5, 'Hey');</code></pre><p>Per stampare l'intestazione "Hey" in una cornice di 5 stelle.</p><p>Sono due usi diversi. Abbiamo bisogno di un modo per determinare se il file viene eseguito come script autonomo o se è richiesto da altri script.</p><p>Qui è dove possiamo usare questa semplice istruzione if:</p><pre><code class="language-js">if (require.main === module) {
  // Il file viene eseguito direttamente (non con require)
}</code></pre><p>Quindi possiamo utilizzare questa condizione per soddisfare i requisiti di utilizzo di cui sopra richiamando la funzione printInFrame in modo diverso:</p><pre><code class="language-js">// In print-in-frame.js

const printInFrame = (size, header) =&gt; {
  console.log('*'.repeat(size));
  console.log(header);
  console.log('*'.repeat(size));
};

if (require.main === module) {
  printInFrame(process.argv[2], process.argv[3]);
} else {
  module.exports = printInFrame;
}</code></pre><p>Quando il file non è richiesto, chiamiamo semplicemente la funzione <code>printInFrame</code> con gli elementi <code>process.argv</code>. Altrimenti, cambiamo semplicemente l'oggetto <code>module.exports</code> in modo che questo sia la funzione stessa <code>printInFrame</code>.</p><h4 id="tutti-i-moduli-verranno-memorizzati-nella-cache"><strong>Tutti i moduli verranno memorizzati nella cache</strong></h4><p>La memorizzazione nella cache è importante da capire. Vorrei usare un semplice esempio per dimostrarlo.</p><p>Supponiamo che tu abbia il seguente file <code>ascii-art.js</code> che stampa un'intestazione dall'aspetto interessante:</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/RbgFBaBdZszHFKEcmsyE8mMW7udDG4NdYofy" class="kg-image" alt="RbgFBaBdZszHFKEcmsyE8mMW7udDG4NdYofy" width="800" height="220" loading="lazy"></figure><p>Vogliamo visualizzare questa intestazione ogni volta che <em><em>richiediamo</em></em> il file. Quindi, quando richiediamo il file due volte, vogliamo che l'intestazione venga visualizzata due volte.</p><pre><code class="language-js">require('./ascii-art') // mostrerà l'intestazione.
require('./ascii-art') // non mostrerà l'intestazione.</code></pre><p>La second richiesta non mostrerà l'intestazione a causa della memorizzazione nella cache dei moduli. Node memorizza nella cache la prima chiamata e non carica il file nella seconda chiamata.</p><p>Possiamo vedere questa cache stampando <code>require.cache</code> dopo la prima richiesta. Il registro della cache è semplicemente un oggetto che ha una proprietà per ogni modulo richiesto. Questi valori di proprietà sono gli oggetti <code>module</code> utilizzati per ogni modulo. Possiamo semplicemente eliminare una proprietà da questo oggetto <code>require.cache</code> per invalidare quella cache. Se lo facciamo, Node ricaricherà il modulo per reinserirlo nella cache.</p><p>Tuttavia, questa non è la soluzione più efficiente per questo caso. La soluzione semplice è avvolgere la riga log <code>ascii-art.js</code> con una funzione ed esportare quella funzione. In questo modo, quando richiediamo il file <code>ascii-art.js</code>, otteniamo una funzione che possiamo eseguire per invocare la stampa ogni volta:</p><pre><code class="language-js">require('./ascii-art')() // mostrerà l'intestazione.
require('./ascii-art')() // mostrerà anche l'intestazione.</code></pre><p>Questo è tutto ciò che ho per questo argomento. Grazie per aver letto. Alla prossima!</p><p>Stai imparando React o Node? Scopri i miei libri:</p><ul><li><a href="http://amzn.to/2peYJZj" rel="noopener">Learn React.js by Building Games</a></li><li><a href="http://amzn.to/2FYfYru" rel="noopener">Node.js Beyond the Basics</a></li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Come utilizzare le variabili di ambiente di Node con un file DotEnv per Node.js e npm ]]>
                </title>
                <description>
                    <![CDATA[ Le variabili di ambiente sono variabili che vengono impostate al di fuori di un programma, spesso tramite un cloud provider o un sistema operativo. In Node, le variabili di ambiente sono un ottimo strumento per configurare in modo sicuro e conveniente cose che non cambiano spesso, come URL, chiavi di ]]>
                </description>
                <link>https://www.freecodecamp.org/italian/news/come-utilizzare-le-variabili-di-ambiente-del-nodo-con-un-file-dotenv-per-node-js-e-npm/</link>
                <guid isPermaLink="false">6202b431b45ad1050e27f450</guid>
                
                    <category>
                        <![CDATA[ NODE ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ nodejs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Angelo Mirabelli ]]>
                </dc:creator>
                <pubDate>Wed, 16 Feb 2022 08:05:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/italian/news/content/images/2022/02/node-env-variables.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Articolo originale:</strong> <a href="https://www.freecodecamp.org/news/how-to-use-node-environment-variables-with-a-dotenv-file-for-node-js-and-npm/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Use Node Environment Variables with a DotEnv File for Node.js and npm</a>
      </p><p>Le variabili di ambiente sono variabili che vengono impostate al di fuori di un programma, spesso tramite un cloud provider o un sistema operativo.</p><p>In Node, le variabili di ambiente sono un ottimo strumento per configurare in modo sicuro e conveniente cose che non cambiano spesso, come URL, chiavi di autenticazione e password.</p><h2 id="come-creare-variabili-d-ambiente"><strong>Come creare variabili d'ambiente</strong></h2><p>Le variabili di ambiente sono supportate nativamente in Node e sono accessibili tramite l'oggetto <code>env</code> (che è una proprietà dell'oggetto globale <code>process</code>).</p><p>Per vederla in azione, puoi creare la tua variabile di ambiente direttamente nel REPL di Node aggiungendo una variabile direttamente all'oggetto <code>process.env</code>.</p><p>Ad esempio, per creare una variabile d'ambiente per memorizzare la <a href="https://www.youtube.com/watch?v=a6iW-8xPw3k">combinazione sul mio bagaglio</a> potrei assegnare la variabile in questo modo: <code>process.env.LUGGAGE_COMBO=“12345”</code>.</p><p>(Una piccola parentesi: le variabili di ambiente sono, per convenzione, generalmente scritte in maiuscolo.)</p><p>Sebbene questo sia a puro titolo d'esempio, non userai mai REPL di Node in questo modo in un'app. Per creare variabili di ambiente nella tua app Node, probabilmente vorrai usare un pacchetto come DotEnv.</p><h2 id="come-usare-dotenv"><strong>Come usare DotEnv</strong></h2><p><a href="https://www.npmjs.com/package/dotenv">DotEnv</a> è un piccolo pacchetto npm che carica automaticamente le variabili di ambiente da un file <code>.env</code> nell'oggetto <code>process.env</code>.</p><p>Per utilizzare DotEnv, prima bisogna installarlo utilizzando il comando: <code>npm i dotenv</code>. Quindi nella tua app, richiedi e configura il pacchetto in questo modo: <code>require('dotenv').config()</code>.</p><p>Tieni presente che alcuni pacchetti come Create React App includono già DotEnv e i provider di servizi cloud potrebbero disporre di metodi diversi per impostare le variabili di ambiente. Quindi assicurati di controllare la documentazione sia per i pacchetti che per provider che stai utilizzando prima di seguire qualsiasi consiglio di questo articolo.</p><h2 id="come-creare-un-file-env"><strong>Come creare un file .env</strong></h2><p>Dopo aver installato e configurato DotEnv, crea un file chiamato <code>.env</code> al livello più alto della struttura dei file. Qui è dove dichiarerai tutte le tue variabili d'ambiente, scritte nel formato &nbsp;<code>NAME=value</code> . Ad esempio, puoi impostare una variabile di porta su 3000 in questo modo: <code>PORT=3000</code>.</p><p>Puoi dichiarare più variabili nel file <code>.env</code>. Ad esempio, puoi impostare variabili di ambiente relative al database come queste:</p><pre><code>DB_HOST=localhost
DB_USER=admin
DB_PASSWORD=password</code></pre><p>Non è necessario racchiudere le stringhe tra virgolette. DotEnv lo fa automaticamente per te.</p><p>Una volta creato questo file, ricorda che non dovresti inviarlo a GitHub poiché può contenere dati sensibili come chiavi di autenticazione e password. Aggiungi il file a .gitignore per evitare di inviarlo accidentalmente a un repository pubblico.</p><h2 id="come-accedere-alle-variabili-d-ambiente"><strong>Come accedere alle variabili d'ambiente</strong></h2><p>Accedere alle tue variabili è semplicissimo! Sono attaccati all'oggetto <code>process.env</code>, quindi puoi accedervi usando il modello <code>process.env.KEY</code>.</p><p>Se hai bisogno di modificare il valore di una qualsiasi delle tue variabili d'ambiente, devi solo modificare il file <code>.env</code>.</p><h2 id="ricapitolando"><strong>Ricapitolando</strong></h2><p>Le variabili di ambiente renderanno il tuo codice più gestibile e più sicuro. Sono facili da configurare con DotEnv e semplici da usare in Node.</p><p>Ora che sai come si fa, puoi creare le tue variabili di ambiente per la tua applicazione Node. Divertiti!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Processi Child di Node.js: tutto ciò che devi sapere ]]>
                </title>
                <description>
                    <![CDATA[ Come usare spawn(), exec(), execFile() e fork() Le prestazioni a singolo thread e non bloccanti in Node.js funzionano alla grande per un singolo processo. Ma alla fine, un processo in una CPU non sarà sufficiente per gestire il crescente carico di lavoro della tua applicazione. Indipendentemente dalla potenza del tuo ]]>
                </description>
                <link>https://www.freecodecamp.org/italian/news/processi-child-di-node-js-tutto-cio-che-devi-sapere/</link>
                <guid isPermaLink="false">61fc2c83184ddc0518e72d0e</guid>
                
                    <category>
                        <![CDATA[ nodejs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Angelo Mirabelli ]]>
                </dc:creator>
                <pubDate>Tue, 15 Feb 2022 05:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/italian/news/content/images/2022/02/1_I56pPhzO1VQw8SIsv8wYNA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Articolo originale:</strong> <a href="https://www.freecodecamp.org/news/node-js-child-processes-everything-you-need-to-know-e69498fe970a/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Node.js Child Processes: Everything you need to know</a>
      </p><h4 id="come-usare-spawn-exec-execfile-e-fork-"><strong>Come usare spawn(), exec(), execFile() e fork()</strong></h4><p>Le prestazioni a singolo thread e non bloccanti in Node.js funzionano alla grande per un singolo processo. Ma alla fine, un processo in una CPU non sarà sufficiente per gestire il crescente carico di lavoro della tua applicazione.</p><p>Indipendentemente dalla potenza del tuo server, un singolo thread può supportare solo un carico limitato.</p><p>Il fatto che Node.js venga eseguito in un singolo thread non significa che non possiamo sfruttare più processi e, ovviamente, anche più macchine.</p><p>L'uso di più processi è il modo migliore per scalare un'applicazione Node. Node.js è progettato per la creazione di applicazioni distribuite con molti nodi. Questo è il motivo per cui si chiama <em><em>Node</em></em> . La scalabilità è incorporata nella piattaforma e non è qualcosa a cui inizi a pensare dopo, nel corso della vita di un'applicazione.</p><blockquote>Questo articolo è un riassunto di parte del <a href="https://www.pluralsight.com/courses/nodejs-advanced" rel="noopener">my Pluralsight course about Node.js</a>. Lì copro contenuti simili in formato video in inglese.</blockquote><p>Tieni presente che avrai bisogno di una buona conoscenza degli <em><em>eventi</em></em> e degli <em><em>stream</em></em> di Node.js prima di leggere questo articolo. Se non l'hai già fatto, ti consiglio di leggere questi altri due articoli prima di leggere questo:</p><p><strong><strong><a href="https://www.freecodecamp.org/news/understanding-node-js-event-driven-architecture-223292fcbc2d/">Understanding Node.js Event-Driven Architecture</a></strong></strong><br><em><em><a href="https://www.freecodecamp.org/news/understanding-node-js-event-driven-architecture-223292fcbc2d/">Most of Node’s objects — like HTTP requests, responses, and streams — implement the EventEmitter module so they can…</a></em></em></p><p><a href="https://medium.freecodecamp.com/node-js-streams-everything-you-need-to-know-c9141306be93" rel="noopener"><strong><strong>Streams: Everything you need to know</strong></strong></a><br><em><em><a href="https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/">Node.js streams have a reputation for being hard to work with, and even harder to understand. Well I’ve got good news…</a></em></em></p><h3 id="il-modulo-child-process"><strong>Il modulo Child Process</strong></h3><p>Possiamo facilmente far girare un child process usando il modulo di Node <code>child_process</code> e quei child process possono facilmente comunicare tra loro con un sistema di messaggistica.</p><p>Il modulo <code>child_process</code> ci consente di accedere alle funzionalità del sistema operativo eseguendo qualsiasi comando di sistema all'interno di un processo figlio.</p><p>Possiamo controllare il flusso di input del child process e ascoltare il suo flusso di output. Possiamo anche controllare gli argomenti da passare al comando del sistema operativo sottostante e possiamo fare tutto ciò che vogliamo con l'output di quel comando. Possiamo, ad esempio, reindirizzare l'output di un comando come input a un altro (proprio come facciamo in Linux) poiché tutti gli input e gli output di questi comandi possono essere a noi disponibili utilizzando <a href="https://medium.freecodecamp.com/node-js-streams-everything-you-need-to-know-c9141306be93" rel="noopener">Node.js streams</a> .</p><p><em><em>Nota che gli esempi che userò in questo articolo sono tutti basati su Linux. Su Windows, devi cambiare </em>questi <em>i comandi </em>co<em>n </em>i<em> loro </em>corrispettivi<em>.</em></em></p><p>Esistono quattro modi diversi per creare un processo figlio in Node: <code>spawn()</code>, <code>fork()</code>, <code>exec()</code>e <code>execFile()</code>.</p><p>Vedremo le differenze tra queste quattro funzioni e quando usarle.</p><p><strong>Child Process generati</strong></p><p>La funzione <code>spawn</code> (generatore) lancia un comando in un nuovo processo e possiamo usarla per passare a quel comando qualsiasi argomento. Ad esempio, ecco il codice per generare un nuovo processo che eseguirà il comando <code>pwd</code>.</p><pre><code>const { spawn } = require('child_process');

const child = spawn('pwd');</code></pre><p>Estraiamo semplicemente la funzione <code>spawn</code> dal modulo <code>child_process</code> e la eseguiamo con il comando del sistema operativo come primo argomento.</p><p>Il risultato dell'esecuzione della funzione <code>spawn</code> (l'oggetto <code>child</code> di sopra) è un'istanza <code>ChildProcess</code> che implementa l' <a href="https://medium.freecodecamp.com/understanding-node-js-event-driven-architecture-223292fcbc2d" rel="noopener">API EventEmitter</a> . Ciò significa che possiamo registrare direttamente i gestori per gli eventi su questo oggetto child. Ad esempio, possiamo fare qualcosa quando il processo child esce registrando un gestore per l'evento <code>exit</code>:</p><pre><code class="language-js">child.on('exit', function (code, signal) {
  console.log('child process exited with ' +
              `code ${code} and signal ${signal}`);
});</code></pre><p>Il gestore sopra ci fornisce il <code>code</code> di uscita per il child process e il <code>signal</code>, se presente, che è stato utilizzato per terminare il processo figlio. Questa variabile <code>signal</code> è nulla quando il child process esce normalmente.</p><p>Gli altri eventi per i quali possiamo registrare i gestori per le istanze di <code>ChildProcess</code> sono <code>disconnect</code>, <code>error</code>, <code>close</code> e <code>message</code>.</p><ul><li>L'evento <code>disconnect</code> viene emesso quando il processo genitore chiama manualmente la funzione <code>child.disconnect</code>.</li><li>L'evento <code>error</code> viene emesso se il processo non può essere generato o terminato.</li><li>L'evento <code>close</code> viene emesso quando i flussi <code>stdio</code> di un processo figlio vengono chiusi.</li><li>L'evento <code>message</code> è quello più importante. Viene emesso quando il processo figlio utilizza la funzione <code>process.send()</code> per inviare messaggi. Questo è il modo in cui i processi genitore/figlio possono comunicare tra loro. Vedremo dopo un esempio.</li></ul><p>Ogni processo figlio ottiene anche i tre flussi standard <code>stdio</code>, a cui possiamo accedere utilizzando <code>child.stdin</code>, <code>child.stdout</code> e <code>child.stderr</code>.</p><p>Quando questi flussi vengono chiusi, il processo figlio che li stava utilizzando emetterà l'evento <code>close</code>. Questo evento <code>close</code> è diverso dall'evento <code>exit</code> perché più processi figlio potrebbero condividere gli stessi flussi <code>stdio</code> e quindi l'uscita di un processo figlio non significa che i canali siano stati chiusi.</p><p>Poiché tutti i flussi sono emettitori di eventi, possiamo ascoltare eventi diversi su quei flussi <code>stdio</code> collegati a ogni processo figlio. A differenza di un processo normale, tuttavia, in un processo figlio, i flussi <code>stdout</code>/ <code>stderr</code> sono flussi leggibili mentre il flusso <code>stdin</code> è scrivibile. Questo è fondamentalmente l'inverso di quei tipi che si trovano in un processo principale. Gli eventi che possiamo usare per quei flussi sono quelli standard. Soprattutto, sui flussi leggibili, possiamo ascoltare l'evento <code>data</code>, che avrà l'output del comando o qualsiasi errore riscontrato durante l'esecuzione del comando:</p><pre><code class="language-js">child.stdout.on('data', (data) =&gt; {
  console.log(`child stdout:\n${data}`);
});

child.stderr.on('data', (data) =&gt; {
  console.error(`child stderr:\n${data}`);
});</code></pre><p>I due gestori precedenti registreranno entrambi i casi <code>stdout</code> e <code>stderr</code> nel processo principale . Quando eseguiamo la funzione <code>spawn</code> di sopra, l'output del comando <code>pwd</code> viene stampato e il processo figlio esce con code <code>0</code>, il che significa che non si è verificato alcun errore.</p><p>Possiamo passare argomenti al comando eseguito dalla funzione <code>spawn</code> utilizzando il secondo argomento della stessa funzione <code>spawn</code>, che è un array di tutti gli argomenti da passare al comando. Ad esempio, per eseguire il comando<code>find</code> sulla directory corrente con un argomento <code>-type f</code> (solo per elencare i file), possiamo fare:</p><pre><code class="language-js">const child = spawn('find', ['.', '-type', 'f']);</code></pre><p>Se si verifica un errore durante l'esecuzione del comando, ad esempio, gli diamo da trovare una destinazione non valida, il gestore dell'evento <code>child.stderr</code> <code>data</code> verrà attivato e il gestore dell'evento <code>exit</code> segnalerà <code>1</code> come codice di uscita, che indica che si è verificato un errore. I valori di errore dipendono dal sistema operativo e dal tipo di errore.</p><p>Un processo figlio <code>stdin</code> è un flusso scrivibile. Possiamo usarlo per inviare un comando di input. Proprio come qualsiasi flusso scrivibile, il modo più semplice per usarlo è utilizzare la funzione <code>pipe</code>. Convogliamo semplicemente un flusso leggibile in un flusso scrivibile. Poiché il processo principale <code>stdin</code> è un flusso leggibile, possiamo convogliarlo in un flusso <code>stdin</code> del processo figlio. Per esempio:</p><pre><code class="language-js">const { spawn } = require('child_process');

const child = spawn('wc');

process.stdin.pipe(child.stdin)

child.stdout.on('data', (data) =&gt; {
  console.log(`child stdout:\n${data}`);
});</code></pre><p>Nell'esempio sopra, il processo figlio richiama il comando <code>wc</code>, che conta righe, parole e caratteri in Linux. Quindi convogliamo il processo principale <code>stdin</code> (che è un flusso leggibile) nel processo figlio <code>stdin</code> (che è un flusso scrivibile). Il risultato di questa combinazione è che otteniamo una modalità di input standard in cui possiamo digitare qualcosa e quando premiamo <code>Ctrl+D</code>, ciò che abbiamo digitato verrà utilizzato come input del comando <code>wc</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/1*s9dQY9GdgkkIf9zC1BL6Bg.gif" class="kg-image" alt="1*s9dQY9GdgkkIf9zC1BL6Bg" width="800" height="450" loading="lazy"><figcaption>Gif catturata dal mio corso Pluralsight — Advanced Node.js</figcaption></figure><p>Possiamo anche convogliare l'input/output standard di più processi l'uno sull'altro, proprio come possiamo fare con i comandi Linux. Ad esempio, possiamo reindirizzare il <code>stdout</code> del comando <code>find</code> allo <code>stdin</code> del comando <code>wc</code> per contare tutti i file nella directory corrente:</p><pre><code class="language-js">const { spawn } = require('child_process');

const find = spawn('find', ['.', '-type', 'f']);
const wc = spawn('wc', ['-l']);

find.stdout.pipe(wc.stdin);

wc.stdout.on('data', (data) =&gt; {
  console.log(`Number of files ${data}`);
});</code></pre><p>Ho aggiunto l'argomento <code>-l</code> al comando <code>wc</code> per fargli contare solo le righe. Quando viene eseguito, il codice sopra produrrà un conteggio di tutti i file in tutte le directory dentro quella corrente.</p><h4 id="la-sintassi-della-shell-e-la-funzione-exec"><strong>La sintassi della shell e la funzione exec</strong></h4><p>Per impostazione predefinita, la funzione <code>spawn</code> non crea una <em><em>shell</em></em> per eseguire il comando che gli passiamo. Questo la rende leggermente più efficiente della funzione <code>exec</code>, che crea una shell. La funzione <code>exec</code> ha un'altra grande differenza. Memorizza l'<em><em>output</em></em> generato dal comando e passa l'intero valore di output a una funzione di callback (invece di utilizzare i flussi, che è ciò che fa invece <code>spawn</code>).</p><p>Ecco l'esempio precedente <code>find | wc</code> implementato con una funzione <code>exec</code>.</p><pre><code class="language-js">const { exec } = require('child_process');

exec('find . -type f | wc -l', (err, stdout, stderr) =&gt; {
  if (err) {
    console.error(`exec error: ${err}`);
    return;
  }

  console.log(`Number of files ${stdout}`);
});</code></pre><p>Poiché la funzione <code>exec</code> utilizza una shell per eseguire il comando, possiamo usare la <em><em>sintassi della shell</em></em> direttamente qui facendo uso della capacità <em><em>pipe</em></em> di shell.</p><p>Nota che l'uso della sintassi della shell comporta un <a href="https://blog.liftsecurity.io/2014/08/19/Avoid-Command-Injection-Node.js/" rel="noopener">rischio per la sicurezza</a> se stai eseguendo qualsiasi tipo di input dinamico fornito esternamente. Un utente può semplicemente eseguire un attacco tramite l'iniezione di comandi utilizzando caratteri della sintassi della shell come ; e $ (ad esempio, <code>command + ’; rm -rf ~’</code>)</p><p>La funzione <code>exec</code> memorizza nel buffer l'output e lo passa alla funzione di callback (il secondo argomento di <code>exec</code>) come argomento <code>stdout</code>. Questo argomento <code>stdout</code> è l'output del comando che vogliamo stampare.</p><p>La funzione <code>exec</code> è una buona scelta se è necessario utilizzare la sintassi della shell e se la dimensione dei dati prevista dal comando è piccola. (Ricorda, <code>exec</code> eseguirà il buffering di tutti i dati in memoria prima di restituirli.)</p><p>La funzione <code>spawn</code> è la scelta migliore quando la dimensione dei dati prevista dal comando è grande, perché i dati verranno trasmessi in streaming con gli oggetti IO standard.</p><p>Possiamo fare in modo che il processo figlio generato erediti gli oggetti IO standard dei suoi genitori, se lo desideriamo, ma anche, cosa più importante, possiamo fare in modo che la funzione <code>spawn</code> utilizzi anche la sintassi della shell. Ecco lo stesso comando <code>find | wc</code> implementato con la funzione <code>spawn</code>:</p><pre><code class="language-js">const child = spawn('find . -type f | wc -l', {
  stdio: 'inherit',
  shell: true
});</code></pre><p>A causa dell'opzione di sopra <code>stdio: 'inherit'</code>, quando eseguiamo il codice, il processo figlio eredita <code>stdin</code>, <code>stdout</code> e <code>stderr</code> dal processo principale. Ciò fa sì che i gestori di eventi dei dati del processo figlio vengano attivati ​​nel canale <code>process.stdout</code>, facendo in modo che lo script emetta immediatamente il risultato.</p><p>Grazie all'opzione precedente <code>shell: true</code>, siamo stati in grado di utilizzare la sintassi della shell nel comando precedente, proprio come abbiamo fatto con <code>exec</code>. Ma con questo codice, otteniamo comunque il vantaggio dello streaming di dati che la funzione <code>spawn</code> ci offre. <em><em>Questo è davvero il meglio di entrambi i mondi.</em></em></p><p>Ci sono alcune altre buone opzioni che possiamo usare nell'ultimo argomento delle funzioni <code>child_process</code> oltre a <code>shell</code> e <code>stdio</code>. Possiamo, ad esempio, usare l'opzione <code>cwd</code> per cambiare la directory di lavoro dello script. Infatti, ecco lo stesso esempio di conteggio di tutti i file eseguito con una funzione <code>spawn</code> che utilizza una shell e con una directory di lavoro impostata nella mia cartella Downloads. L'opzione <code>cwd</code> qui farà sì che lo script conteggi tutti i file che ho in <code>~/Downloads</code>:</p><pre><code class="language-js">const child = spawn('find . -type f | wc -l', {
  stdio: 'inherit',
  shell: true,
  cwd: '/Users/samer/Downloads'
});</code></pre><p>Un'altra opzione che possiamo usare è l'opzione <code>env</code> per specificare le variabili di ambiente che saranno visibili al nuovo processo figlio. L'impostazione predefinita per questa opzione è <code>process.env</code> che fornisce a qualsiasi comando l'accesso all'ambiente del processo corrente. Se vogliamo sovrascrivere quel comportamento, possiamo semplicemente passare un oggetto vuoto all'opzione <code>env</code> o nuovi valori da considerare come le uniche variabili d'ambiente:</p><pre><code class="language-js">const child = spawn('echo $ANSWER', {
  stdio: 'inherit',
  shell: true,
  env: { ANSWER: 42 },
});</code></pre><p>Il comando echo di sopra non ha accesso alle variabili di ambiente del processo padre. Ad esempio, non può accedere a <code>$HOME</code>, ma può accedere a <code>$ANSWER</code> perché è stata passata come variabile di ambiente personalizzata tramite l'opzione <code>env</code>.</p><p>Un'ultima importante opzione del processo figlio da spiegare qui è l'opzione <code>detached</code>, che fa sì che il processo figlio venga eseguito indipendentemente dal suo processo padre.</p><p>Supponendo di avere un file <code>timer.js</code> che mantiene occupato il ciclo degli eventi:</p><pre><code class="language-js">setTimeout(() =&gt; {  
  // keep the event loop busy
}, 20000);</code></pre><p>Possiamo eseguirlo in background usando l'opzione <code>detached</code>:</p><pre><code class="language-js">const { spawn } = require('child_process');

const child = spawn('node', ['timer.js'], {
  detached: true,
  stdio: 'ignore'
});

child.unref();</code></pre><p>L'esatto comportamento dei processi figli distaccati dipende dal sistema operativo. Su Windows, avrà la propria finestra della console mentre su Linux il processo figlio distaccato sarà nominato leader di un nuovo gruppo di processi e sessione.</p><p>Se la funzione <code>unref</code> viene chiamata sul processo distaccato, il processo padre può uscire indipendentemente dal figlio. Questo può essere utile se il figlio sta eseguendo un processo di lunga durata, ma per mantenerlo in esecuzione in background le configurazioni <code>stdio</code> del figlio devono anch'esse essere indipendenti dal genitore.</p><p>L'esempio sopra eseguirà uno script del nodo ( <code>timer.js</code>) in background staccando e ignorando anche i suoi descrittori di file <code>stdio</code> del padre in modo che il genitore possa terminare mentre il figlio continuerà a essere eseguito in background.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/1*WhvMs8zv-WS6v7nDXmDUzw.gif" class="kg-image" alt="1*WhvMs8zv-WS6v7nDXmDUzw" width="800" height="450" loading="lazy"><figcaption>Gif catturata dal mio corso Pluralsight — Advanced Node.js</figcaption></figure><h4 id="la-funzione-execfile"><strong>La funzione execFile</strong></h4><p>Se devi eseguire un file senza usare una shell, la funzione <code>execFile</code> è ciò di cui hai bisogno. Si comporta esattamente come la funzione <code>exec</code>, ma non usa una shell, il che la rende un po' più efficiente. Su Windows, alcuni file non possono essere eseguiti da soli, come i file <code>.bat</code> o <code>.cmd</code>. Questi file non possono essere eseguiti con <code>execFile</code> e per eseguirli con <code>exec</code> o <code>spawn</code> è necessario che la shell sia impostata su true.</p><h4 id="le-funzioni-sync"><strong>Le funzioni *Sync</strong></h4><p>Le funzioni <code>spawn</code>, <code>exec</code>, ed <code>execFile</code> del modulo <code>child_process</code> hanno anche versioni bloccanti sincrone che attenderanno fino all'uscita del processo figlio.</p><pre><code>const { 
  spawnSync, 
  execSync, 
  execFileSync,
} = require('child_process');</code></pre><p>Tali versioni sincrone sono potenzialmente utili quando si tenta di semplificare le attività di scripting o qualsiasi attività di elaborazione all'avvio, ma in caso contrario dovrebbero essere evitate.</p><h4 id="la-funzione-fork-"><strong>La funzione fork()</strong></h4><p>La funzione <code>fork</code> è una variante della funzione <code>spawn</code> per la generazione di nodi di processi. La più grande differenza tra <code>spawn</code> e <code>fork</code> è che viene stabilito un canale di comunicazione con il processo figlio quando si utilizza <code>fork</code>, quindi possiamo utilizzare la funzione <code>send</code> sul processo fork (biforcato) insieme allo stesso oggetto globale <code>process</code> per scambiare messaggi tra il processo padre e il processo fork. Lo facciamo attraverso l'interfaccia <code>EventEmitter</code> del modulo. Ecco un esempio:</p><p>Il file principale <code>parent.js</code>,:</p><pre><code class="language-js">const { fork } = require('child_process');

const forked = fork('child.js');

forked.on('message', (msg) =&gt; {
  console.log('Message from child', msg);
});

forked.send({ hello: 'world' });</code></pre><p>Il file figlio <code>child.js</code>,:</p><pre><code class="language-js">process.on('message', (msg) =&gt; {
  console.log('Message from parent:', msg);
});

let counter = 0;

setInterval(() =&gt; {
  process.send({ counter: counter++ });
}, 1000);</code></pre><p>Nel file padre di sopra, eseguiamo il fork di <code>child.js</code>(che eseguirà il file con il comando <code>node</code>) e quindi ascoltiamo l'evento <code>message</code>. L'evento <code>message</code> verrà emesso ogni volta che il figlio utilizza <code>process.send</code>, cosa che stiamo facendo ogni secondo.</p><p>Per passare i messaggi dal genitore al figlio, possiamo eseguire la funzione <code>send</code> sull'oggetto fork stesso e quindi, nello script figlio, possiamo ascoltare l'evento <code>message</code> sull'oggetto globale <code>process</code>.</p><p>Quando si esegue il file <code>parent.js</code> di sopra, questo invierà prima l'oggetto <code>{ hello: 'world' }</code> che verrà stampato dal processo figlio il quale invierà un valore contatore incrementato ogni secondo, che verrà stampato dal processo padre.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/1*GOIOTAZTcn40qZ3JwgsrNA.gif" class="kg-image" alt="1*GOIOTAZTcn40qZ3JwgsrNA" width="800" height="450" loading="lazy"><figcaption>Screenshot catturato dal mio corso Pluralsight — Advanced Node.js</figcaption></figure><p>Facciamo un esempio più pratico sulla funzione <code>fork</code>.</p><p>Supponiamo di avere un server http che gestisce due endpoint. Uno di questi endpoint ( <code>/compute</code> di sotto) è computazionalmente costoso e richiederà alcuni secondi per essere completato. Possiamo simulare ciò usando un lungo ciclo for:</p><pre><code class="language-js">const http = require('http');

const longComputation = () =&gt; {
  let sum = 0;
  for (let i = 0; i &lt; 1e9; i++) {
    sum += i;
  };
  return sum;
};

const server = http.createServer();

server.on('request', (req, res) =&gt; {
  if (req.url === '/compute') {
    const sum = longComputation();
    return res.end(`Sum is ${sum}`);
  } else {
    res.end('Ok')
  }
});

server.listen(3000);</code></pre><p>Questo programma ha un grosso problema; quando viene richiesto l'endpoint <code>/compute</code> , il server non sarà in grado di gestire altre richieste perché il ciclo di eventi è occupato con la lunga operazione del ciclo for.</p><p>Ci sono alcuni modi con cui possiamo risolvere questo problema a seconda della natura dell'operazione lunga, ma una soluzione che funziona per tutte le operazioni è semplicemente spostare l'operazione di calcolo in un altro processo usando <code>fork</code>.</p><p>Per prima cosa spostiamo l'intera funzione <code>longComputation</code> nel proprio file e facciamo in modo che invochi quella funzione quando richiesto tramite un messaggio dal processo principale:</p><p>In un nuovo file <code>compute.js</code>:</p><pre><code class="language-js">const longComputation = () =&gt; {
  let sum = 0;
  for (let i = 0; i &lt; 1e9; i++) {
    sum += i;
  };
  return sum;
};

process.on('message', (msg) =&gt; {
  const sum = longComputation();
  process.send(sum);
});</code></pre><p>Ora, invece di eseguire la lunga operazione nel ciclo di eventi del processo principale, possiamo fare il <code>fork</code> del file <code>compute.js</code> e utilizzare l'interfaccia dei messaggi per comunicare i messaggi tra il server e il processo biforcato.</p><pre><code class="language-js">const http = require('http');
const { fork } = require('child_process');

const server = http.createServer();

server.on('request', (req, res) =&gt; {
  if (req.url === '/compute') {
    const compute = fork('compute.js');
    compute.send('start');
    compute.on('message', sum =&gt; {
      res.end(`Sum is ${sum}`);
    });
  } else {
    res.end('Ok')
  }
});

server.listen(3000);</code></pre><p>Ora con il codice sopra, quando si verifica una richiesta <code>/compute</code>, inviamo semplicemente un messaggio al processo biforcato per avviare l'esecuzione dell'operazione lunga. Il ciclo di eventi del processo principale non verrà bloccato.</p><p>Una volta che il processo fork ha terminato con quella lunga operazione, può inviare il suo risultato al processo padre usando <code>process.send</code>.</p><p>Nel processo padre, ascoltiamo l'evento <code>message</code> sul processo figlio biforcato. Quando avremo quell'evento, avremo un valore <code>sum</code> pronto da inviare all'utente richiedente su http.</p><p>Il codice sopra è, ovviamente, limitato dal numero di processi che possiamo biforcare, ma quando lo eseguiamo e richiediamo l'endpoint di calcolo lungo su http, il server principale non è affatto bloccato e può accettare ulteriori richieste.</p><p>Il modulo <code>cluster</code> di Node, che è l'argomento del mio prossimo articolo, si basa su questa idea di fork del processo figlio e bilanciamento del carico delle richieste tra i molti fork che possiamo creare su qualsiasi sistema.</p><p>Questo è tutto per questo argomento. Grazie per aver letto! Alla prossima!</p><p>Imparare React o Node? Scopri i miei libri:</p><ul><li><a href="http://amzn.to/2peYJZj" rel="noopener">Impara React.js costruendo giochi</a></li><li><a href="http://amzn.to/2FYfYru" rel="noopener">Node.js oltre le basi</a></li></ul> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
