Liberaci dall’inferno delle dipendenze
La maggior parte dei servizi e delle applicazioni moderne ha una massa di dipendenze che vivono in una cartella node-modules
in continua crescita. Generalmente molte di queste librerie vengono attivamente mantenute, modificate e aggiornate. Se le tue dipendenze sono gestite male, puoi trovarti rapidamente nell’inferno delle dipendenze.
Se non hai familiarità con npm, dai un’occhiata qui prima di leggere su
Shopping Grocery Shopping
Quando si avvia un’applicazione node, uno dei primi passi è l’esecuzione di npm install
. Quando lo esegui, node controllerà un file chiamato package.json
nella base del tuo progetto. Se viene trovato quel file, utilizzerà la sezione dependency
come una sorta di “lista della spesa” per andare a raccogliere “ingredienti” (bit di codice) richiesti dall’applicazione.
Il “negozio di alimentari” in questo caso è qualcosa che npm chiama registry
. Per impostazione predefinita, l’app node cercherà nel registro npm pubblico questi pacchetti, dove sarà la maggior parte di tutto ciò di cui hai bisogno (i registri privati possono essere creati per il codice proprietario e quant’altro). Se il pacchetto viene trovato nel registro, node inserisce tale “ingrediente” in una directory node_modules
alla base del progetto.
È importante notare che i pacchetti richiesti possono avere la propria “lista della spesa” (pacchetto.json) e tutte queste dipendenze annidate devono essere risolte prima che l’app passi alla dipendenza successiva nel proprio pacchetto.json.
⬆️ Versioni, Care Carets e Wild Wildcards
Le versioni delle tue dipendenze sono generalmente qualcosa come v1.3.5
. Questo è chiamato semantic versioning, o semver. Con semver, i numeri rappresentano le modifiche al codice in gravità variabile – MAJOR.MINOR.PATCH
.
Dai loro documenti –
Versione PRINCIPALE quando si apportano modifiche API incompatibili, versione MINORE
quando si aggiungono funzionalità in modo compatibile con le versioni precedenti e versione PATCH
quando si apportano correzioni di bug compatibili con le versioni precedenti.
Con questo in mente, molte persone vogliono aggiornare automaticamente la loro app con qualsiasi nuova roba fresca che le loro dipendenze potrebbero avere in modifiche più recenti e non infruttuose.
Il prefisso con tilde
~
ti darà nuovi aggiornamentiPATCH
, ma non maggiori o minori. Quindi~1.3.1
potrebbe installare1.3.9
, ma non1.4.0
Il prefisso con cursore
^
ti darà qualsiasi nuova versionePATCH
eMINOR
, ma non maggiore. Così^1.3.1
potrebbe installare1.4.9
ma non1.5.0
diamo un’occhiata al nostro codice di esempio dell’albero delle dipendenze:
my-breakfast | | milk | |coffee-script
Ok, più simile a un bastone, ma speriamo che la catena di dipendenza è chiaro. Il nostro pacchetto.json richiede la versione v0.5.0
in particolare di milk
, ma milk richiede coffee-script
ovunque da 0.9.6
– 1.0.0
. npm install
viene eseguito, sviluppiamo la nostra app, tutto è hunky-dory.
Now Ora andiamo avanti velocemente di 2 mesi. Qualcuno trova il tuo progetto e vuole contribuire. Si biforcano e clonano il tuo repository, eseguono npm install
, aaaae non funziona. “Ma ha funzionato sulla mia macchina!”piangi. Quando il tuo collaboratore ha installato i moduli del nodo, gli è stata garantita una versione specifica di milk
, ma hanno ottenuto una versione diversa di coffee-script
perché il pacchetto di milk
.json ha usato semver.
Setting impostazione delle dipendenze in stone
Una soluzione a questo è usare un file package-lock.json
. Questo file ti dà un controllo molto granulare sulle versioni di ogni dipendenza che installi. Se il tuo package.json
è come la lista della spesa, allora il tuo package-lock.json
è come un budget. Puoi avere i cereali, ma sarà il marchio del negozio invece di Cap’n Crunch. Questa specificità corre lungo ogni ramo del tuo albero delle dipendenze. Devi avere un package.json
se vuoi usare un file di blocco (package.json
fa molto di più della semplice gestione delle dipendenze, questo è solo il focus di questo post).
Wrapping Wrapping up
Personalmente ritengo che un file package-lock.json
debba sempre essere usato (nelle versioni più recenti di npm, in realtà viene generato automaticamente). Rende tutto più affidabile in ambienti e distribuzioni. Ecco alcune ultime piccole pepite per sperare di aiutare quando si tratta di dipendenze:
-
npm install --save
aggiornerà automaticamente il file di blocco e il pacchetto.json con quel pacchetto. -
npm ci
invece dinpm install
ricostruirà automaticamente i moduli del nodo e verrà creato dal file di blocco. È un comando davvero utile per CI / CD e generalmente è meglio usare in tandem con un lockfile. - Per progetti più grandi e dipendenze super robuste, controlla docker e contenitori. Può funzionare quasi come una macchina virtuale che contiene perfettamente il codice e le sue dipendenze, ed è clonato per promuovere in ambienti diversi. Quindi spero che tu finisca con molto meno problemi “ha funzionato sulla mia macchina”.