Menu

Basi di npm: install, init, update e gestione delle dipendenze

Come funziona davvero npm: installare pacchetti, init, dipendenze di sviluppo, aggiornamenti e il modello mentale dietro node_modules e il lockfile.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Cos'è davvero npm

npm sono tre cose riunite sotto un unico nome. È un registro: un enorme database pubblico di pacchetti JavaScript su npmjs.com. È uno strumento da riga di comando che arriva con Node.js per installare e gestire quei pacchetti. Ed è una specifica (il formato di package.json) che descrive ciò di cui un progetto ha bisogno.

Quando esegui npm install express, la CLI parla con il registro, scarica express e tutto ciò da cui dipende, mette i file in una cartella chiamata node_modules e registra il pacchetto e la sua versione nel tuo package.json. Questo è tutto il giro.

Se hai installato Node.js, ce l'hai già. Controlla:

node --version
npm --version

Se entrambi stampano una versione, sei a posto.

Iniziare un progetto: npm init

Ogni progetto npm ha bisogno di un package.json. È il manifesto: elenca il nome del progetto, la versione, gli script e le dipendenze. Il modo più veloce per crearne uno è npm init -y, che accetta tutti i valori predefiniti:

mkdir my-app
cd my-app
npm init -y

Questo scrive qualcosa del genere:

{
  "name": "my-app",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Senza -y, npm ti guida campo per campo in modo interattivo. In entrambi i casi ottieni un package.json, il file a cui si aggancia tutto il resto. Vedremo i suoi campi nel dettaglio nella prossima pagina.

Installare un pacchetto

Una volta che hai un package.json, installa un pacchetto con npm install (o npm i in breve):

npm install lodash

Succedono tre cose:

  1. npm scarica lodash e le sue dipendenze dentro node_modules/.
  2. Aggiunge "lodash": "^4.17.21" (o l'ultima versione disponibile) alla sezione dependencies di package.json.
  3. Scrive un package-lock.json che registra le versioni esatte di ogni pacchetto dell'albero.

Ora puoi usarlo:

La chiamata require (o import in un progetto ESM) trova il pacchetto cercando dentro node_modules. Non scrivi un percorso: se ne occupa il resolver dei moduli di Node.

dependencies e devDependencies

Non tutti i pacchetti servono quando la tua app gira in produzione. Framework di test, linter e bundler contano solo durante lo sviluppo. Installali con --save-dev (o -D):

npm install --save-dev jest
npm install -D eslint prettier

Questi finiscono in devDependencies invece che in dependencies:

{
  "dependencies": {
    "lodash": "^4.17.21"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "eslint": "^8.57.0",
    "prettier": "^3.2.5"
  }
}

Su un server di produzione, npm install --omit=dev salta del tutto la sezione di sviluppo, rendendo l'installazione più piccola e veloce. Fare bene questa divisione conta più di quanto sembri: un webpack messo per sbaglio in dependencies appesantisce ogni deploy in produzione.

Installare tutto in una volta

Quando cloni un repository che ha già un package.json, non elenchi i pacchetti uno per uno. Esegui semplicemente:

npm install

Senza argomenti, npm legge package.json (e rispetta le versioni esatte di package-lock.json) e installa l'intero albero dentro node_modules. È la prima cosa da eseguire dopo ogni checkout nuovo.

È anche per questo che node_modules va in .gitignore. È riproducibile a partire dal lockfile, è enorme e cambia ogni volta che qualcuno esegue npm install. Fai il commit di package.json e package-lock.json; lascia che tutti gli altri rigenerino node_modules da soli.

Aggiornare i pacchetti

npm outdated mostra cosa è rimasto indietro:

npm outdated

Vedrai una tabella con le colonne Current, Wanted e Latest. Wanted è la versione più recente consentita dall'intervallo in package.json (per ^4.17.21, qualsiasi versione sotto 5.0.0). Latest è la versione più recente pubblicata, che potrebbe essere una major che non hai ancora scelto di adottare.

Per aggiornare dentro l'intervallo consentito:

npm update

Per passare davvero all'ultima versione, compresi i salti di versione major, installa di nuovo il pacchetto con @latest:

npm install lodash@latest

I salti di versione major possono rompere il tuo codice: è proprio quello che il numero di versione sta segnalando. Leggi il changelog prima di attraversarne uno.

Disinstallare

Rimuovere un pacchetto è l'operazione simmetrica:

npm uninstall lodash

Lo toglie da node_modules ed elimina la voce da package.json. Aggiungi -D se era una dipendenza di sviluppo (npm se ne accorge comunque, ma essere espliciti evita sorprese negli script).

Globale o locale

Quasi ogni installazione dovrebbe essere locale, fissata a un solo progetto dentro il suo node_modules. L'eccezione sono gli strumenti da riga di comando che vuoi avere ovunque:

npm install -g typescript
npm install -g http-server

Un'installazione globale mette lo strumento in una posizione di sistema e la sua voce bin nel tuo PATH, così puoi eseguire tsc o http-server da qualsiasi cartella. Ma le installazioni globali non vengono tracciate per progetto e possono disallinearsi tra una macchina e l'altra.

Una via di mezzo migliore per i comandi occasionali è npx, che arriva insieme a npm:

npx create-react-app my-app
npx prettier --write .

npx esegue un pacchetto senza installarlo globalmente: lo scarica al momento, lo esegue e hai finito. Per gli strumenti che usi una volta sola, è più pulito di un'installazione globale permanente.

Un promemoria minimo

I comandi che userai davvero ogni giorno:

npm init -y                     # create package.json
npm install                     # install everything in package.json
npm install <pkg>               # add a runtime dependency
npm install -D <pkg>            # add a dev dependency
npm install -g <pkg>            # install a CLI tool globally
npm uninstall <pkg>             # remove a dependency
npm outdated                    # see what's out of date
npm update                      # update within allowed ranges
npm install <pkg>@latest        # jump to the newest version
npm run <script>                # run a script from package.json
npx <pkg>                       # run a package without installing it

Questo è gran parte di npm. Il resto (pubblicazione, workspace, pacchetti con scope) puoi impararlo quando ti serve.

Cosa c'è davvero in node_modules

Un ultimo modello mentale. node_modules è una cartella più o meno piatta che contiene ogni pacchetto da cui dipende il tuo progetto, più tutto ciò da cui dipendono quei pacchetti, in modo transitivo. Installi un pacchetto e potresti tirartene dietro cento: è normale. npm elimina i duplicati dove può, quindi due pacchetti che dipendono dalla stessa versione di lodash ne condividono una sola copia.

Il lockfile (package-lock.json) registra la versione esatta risolta di ognuno di quei pacchetti. È questo che rende le build riproducibili: due sviluppatori che eseguono npm install dallo stesso lockfile ottengono alberi identici byte per byte, anche a mesi di distanza.

Tratta node_modules come un output generato. Non modificare mai i file al suo interno: le tue modifiche spariranno alla prossima installazione di chiunque.

Prossimo passo: package.json

package.json è il file che npm continua a leggere e riscrivere dietro le quinte. Conoscere i suoi campi (scripts, main, type, intervalli di versione, engines) è ciò che trasforma npm da scatola nera a qualcosa che controlli tu. È l'argomento della prossima pagina.

Domande frequenti

Cos'è npm?

npm è il gestore di pacchetti predefinito di Node.js. Arriva insieme a Node, ospita un enorme registro pubblico di pacchetti JavaScript e fornisce uno strumento da riga di comando per installarli, aggiornarli e pubblicarli. Quando esegui npm install lodash, npm scarica lodash dal registro dentro node_modules e lo registra in package.json.

Qual è la differenza tra dependencies e devDependencies?

Le dependencies sono i pacchetti di cui la tua app ha bisogno per girare in produzione, come express o react. Le devDependencies servono solo durante lo sviluppo o la build: test runner, bundler, linter. Installi queste ultime con npm install --save-dev <pkg> (o -D). In produzione, npm install --omit=dev salta le devDependencies.

Devo fare il commit di node_modules su git?

No. node_modules può facilmente pesare centinaia di megabyte ed è completamente riproducibile a partire da package.json + package-lock.json. Aggiungilo a .gitignore e fai il commit del lockfile. Chiunque cloni il tuo repository esegue npm install e ottiene esattamente lo stesso albero di dipendenze.

Cosa significa installazione globale o locale con npm?

Un'installazione locale (npm install <pkg>) mette il pacchetto dentro il node_modules del tuo progetto e lo registra in package.json. Un'installazione globale (npm install -g <pkg>) lo installa a livello di sistema, di solito per strumenti da riga di comando che vuoi avere a disposizione ovunque. Per le dipendenze di progetto preferisci le installazioni locali, così le versioni restano fissate progetto per progetto.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA