Node.js 20.0.0 è stato rilasciato il 18 aprile 2023 e rappresenta la prima versione ufficiale della serie 20. La versione 20 è una versione LTS e quindi rimarrà per parecchio tempo in circolazione: sarà supportata fino al 30 aprile 2026.

Potete trovare tutte le spiegazioni sulla politica dei rilasci di Node.js (LTS e non) nel capitolo 2 "Scegliere e installare una versione di Node.js" del libro.

La versione 20.0.0 è stata solo la prima versione della serie 20 e, ad oggi (dicembre 2024), quasi altre 30 versioni della stessa serie sono state rilasciate, arrivando alla 20.18.0.

Le novità principali della 20.0.0

Le novità principali introdotte nella versione 20.0.0 di Node.js sono le quattro elencate di seguito.

Permission model

Il permission model permette di avviare un’applicazione limitando le risorse a cui Node.js (e quindi l’applicazione in esecuzione) può accedere e cosa può farci.

Lo scopo del permission model rappresenta un altro passo importante verso il miglioramento della sicurezza delle applicazioni Node.js.

Con questo modello diventa possibile limitare l’accesso a risorse specifiche durante l’esecuzione del programma, come operazioni sul file system, la creazione di child process e di worker thread.

La funzionalità è sperimentale e richiede l’utilizzo del flag --experimental-permission per essere attivata.

Esempio che abilita solo la lettura e scrittura sul filesystem:

node --experimental-permission --allow-fs-read=* --allow-fs-write=* index.js

Documentazione a questo link.

V8 versione 11.3

La nuova versione di V8 inclusa in Node.js è la 11.3 che porta nuove aggiunte alle API JavaScript:

  • il metodo String.prototype.isWellFormed() per verificare se la stringa è valida rispetto a UTF-16, e String.prototype.toWellFormed() per trasformarla in una valida (proposal-is-usv-string);
  • i metodi toReversed(), toSorted(compareFn), toSpliced(start, deleteCount, ...items) e with(index, value) per trasformare l’Array (o un TypedArray e derivati - es. Uint8Array) e restituire una nuova copia senza alterare l’originale (proposal-change-array-by-copy);
  • supporto per il ridimensionamento di ArrayBuffer e SharedArrayBuffer (proposal);
  • nuove funionalità per RegExp (proposal-regexp-v-flag);
  • supporto per la ricorsione di coda in WebAssembly (proposal-tail-call);

Test runner stabile

Il test runner integrato in Node.js e introdotto come experimental nella serie 18 è ora segnato come stabile e pronto per la produzione.

import { test } from "node:test";
import assert from "node:assert";

test("an addition", () => {
  assert.strictEqual(1 + 1, 2);
});

ARM64 per Windows

Il supporto alla piattaforma ARM64 Windows è ora passata al tier 2 e permette l’esecuzione nativa di Node.js. Ogni nuova build di Node.js è ora verificata anche per ARM64 Windows affinché non ci siano bug o regressioni.

Potete trovare tutte le spiegazioni sui livelli (tier) di supporto delle piattaforme di Node.js capitolo 2 "Scegliere e installare una versione di Node.js" del libro.

Altre novità

  • il parser di URL Ada è stato aggiornato alla versione 2.0 con i relativi miglioramenti di prestazioni;
  • i loader ESM personalizzati sono ora eseguiti in un thread separato;
  • import.meta.resolve() viene eseguito in modo sincrono in modo simile a quanto fatto dai browser;
  • le funzioni delle API Web Crypto API sono validate usando la specifica per migliorare la compatibilità con le altre implementazioni;

20.1.0

Rilascio con correzioni e piccole migliore sulle funzionalità esistenti

20.2.0

Rlascio con correzioni e piccole migliore sulle funzionalità esistenti

20.3.0

La modifica principale è l’aggiornamento di libuv alla versione 1.45.0. Questa versione aggiunge il supporto a io_uring per alcune operazioni asincrone:

  • read, write
  • fsync, fdatasync
  • stat, fstat, lstat

Questa funzionalità si attiva solo quando Node.js viene eseguito su Linux e solo se il kernel in uso è almeno il 5.13.

Il throughput aumenta di 8 volte rispetto all’utilizzo del thread pool standard per questo tipo di operazioni.

Potete trovare tutte le spiegazioni sul thread pool interno di Node.js capitolo 7 "Concorrenza e parallelismo" del libro.

20.3.1

Questo rilascio contiene patch di sicurezza, principalmente correlati al permission model introdotto con la 20.0.0. C’è un motivo se è segnato come experimental, ed è proprio questo.

20.4.0

Mock timers

Il modulo node:test riceve la possibilità di usare dei mock per i timer (setTimeout, setInterval più tutti quelli presenti in node:timers e node:timers/promises). Questi mock permettono di scrivere dei test che dipendono dal tempo senza la necessità di dover effettivamente attendere il passaggio di quel tempo.

Grazie a questi mock i test diventano più semplici e il loro risultanto più certo. Tra le funzionalità esposte da questi mock ci sono quelle di poter far avanzare il tempo, scegliere quale timer attivare e quale rilasciare.

Un esempio che mostra le varie possibilità:

import assert from "node:assert";
import { test } from "node:test";

test("mocks setTimeout to be executed synchronously without having to actually wait for it", (context) => {
  const fn = context.mock.fn();
  // Optionally choose what to mock
  context.mock.timers.enable(["setTimeout"]);
  const nineSecs = 9000;
  setTimeout(fn, nineSecs);

  const threeSeconds = 3000;
  context.mock.timers.tick(threeSeconds);
  context.mock.timers.tick(threeSeconds);
  context.mock.timers.tick(threeSeconds);

  assert.strictEqual(fn.mock.callCount(), 1);
});

Supporto per la gestione esplicita delle risorse

È stato aggiunto il supporto alla proposal-explicit-resource-management per fornire il supporto, a livello di linguaggio, del pattern di gestione delle risorse.

20.5.0

Rilascio con correzioni e piccole migliore sulle funzionalità esistenti.

20.5.1

Questo rilascio contiene patch di sicurezza, principalmente correlati al permission model introdotto con la 20.0.0. Sì, di nuovo.

20.6.0

Supporto per i file .env

Node.js ora supporta i file .env per configurare le variabili d’ambiente. Questo permette di definire le variabili d’ambiente direttamente nei file .env, eliminando la necessità di includerle nel package.json o di usare moduli esterni.

I file .env devono essere in formato INI dove ogni linea è nel formato chiave-valore per una singola variabile d’ambiente. Per far leggere il file ad un’applicazione è necessario usare un’opzione aggiuntiva: node --env-file=config.env index.js.

Dato il file config.env:

SECRET=my-password
DB_URI=mongodb://localhost:27017

È possibile accedere a queste variabili attraverso process.env.SECRET e process.env.DB_URI.

Anche la variabile NODE_OPTIONS è definibile all’interno di questo file.

Altre novità

  • import.meta.resolve(specifier) non è più sperimentale e può essere usata per ottnere l’URL in cui viene risolto il parametro specifier. Questo è simile a require.resolve() di CommonJS ed è stato aggiunto per allineare il funzionamento di Node.js con quello dei browser e degli altri runtime che implementano la specifica ESM;
  • API register() e hook initialize per i moduli ESM, hook load() anche per i moduli CommonJS;
  • aggiunto il supporto per il garbace collector cppgc (Oilpan);
Potete trovare tutte le spiegazioni sui moduli di Node.js (sia ESM che CommonJS) nel capitolo 8 "Moduli e dipendenze" del libro.

20.6.1

Correzioni.

20.7.0

  • supporto per il passaggio di più file .env attraverso l’opzione --env-file;
  • supporto per più opzioni --allow-fs-*;
  • l’output dei test inviato al reporter include la posizione del file di test eseguito e le linee/colonne in caso d’errore;

20.8.0

Performance degli Stream

In questa versione le performance degli stream (readable e writable) sono migliorate. La creazione e distruzione degli stream è ora più veloce come anche l’utilizzo della memoria usata da ogni stream è diminuita.

Anche i readable webstream hanno subito miglioramenti di performance.

Altro

  • aggiunto il reporter nel formato junit al test runner;
  • refactor della gestione della memoria del modulo vm che risolve diversi memory leak;

20.8.1

Release di sicurezza di ottobre 2023

20.9.0

Questa release segna il passaggio della serie 20 di Node.js nello stato di Active LTS.

20.10.0

  • aggiunto il supporto all’opzione flush per assicurarsi che i dati vengano effettivamente scritti sul disco prima che la funzione fs.writeFile() (e le altre simili) termini l’esecuzione;
  • migliorate le performance degli stream;
  • aggiunto il flag --experimental-default-type per cambiare il modo in cui i moduli devono essere interpretati (se non diversamente specificato);
  • aggiunto il flag --experimental-detect-module per caricare un modulo ambiguo (es. se la sua estensione è .js) trattandolo come ES se la sua sintassi interna corrisponde;
  • aggiunto il flag --experimental-websocket per attivare un client WebSocket globale che rispetta lo standard;

20.11.0

  • aggiunto il supporto a import.meta.dirname e import.meta.filename per i moduli ECMAScript;

20.11.1

Release di sicurezza.

20.12.0

util.styleText

È stata aggiunta la funzione util.styleText(format, text) che restituisce il testo formattato secondo lo stile indicato (colori e enfasi).

const { styleText } = require("node:util");
const errorMessage = styleText("red", "Error!");
console.log(errorMessage);

crypto.hash()

La nuova funzione di utilità crypto.hash() permette di calcolare un hash usando una singola chiamate. Questo processo è fino a due volte più veloce del metodo createHash() quando l’input è inferiore ai 5MB e richiede meno memoria.

const crypto = require("node:crypto");

// Hashing a string and return the result as a hex-encoded string.
const string = "Node.js";
// 10b3493287f831e81a438811a1ffba01f8cec4b7
console.log(crypto.hash("sha1", string));

Caricamento e parsing di variabili d’ambiente

Sono disponibili due nuove funzioni. La prima è process.loadEnvFile(path) che carica il file .env indicato (o quello presente nella directory attuale se il parametro non viene specificato).

La seconda è util.parseEnv(content) che effettua il parsing di una stringa nello stesso formato dei file .env (es. util.parseEnv('HELLO=world')).

Nuovi eventi per net.createConnection

L’utilizzo di net.createConnection espone tre nuovi eventi legati al tentativo di connessione: connectionAttempt, connectionAttemptFailed e connectionAttemptTimeout.

Novità nel permission model

È stato aggiunto il nuovo flag -allow-addons che permette l’utilizzo degli addon quando il permission model è attivo. Inoltre, il già esistente --allow-fs-* è stato modificato per permettere l’utilizzo di path relativi.

20.12.1

Release di sicurezza.

20.12.2

Release di sicurezza.

20.13.0

  • le performance della codifica e decodifica di base64 e base64url sono migliorate in modo importante;
  • CustomEvent è segnato come stabile
  • le API di fs/promises aggiungono uno stacktrace in caso d’errore;
  • aggiunto il supporto per i typed arrays negli stream;
  • util.styleText supporta un array di formati: console.log(util.styleText(['underline', 'italic'], 'My italic underlined message'));
  • Watch Mode è ora stabile;

20.13.1

Release con correzioni.

20.14.0

Release con aggiornamenti interni.

20.15.0

  • aggiunta la funzione zlib.crc32();
  • aggiunto il flag --inspect-wait per attendere il collegamento del debugger;
  • aggiunto il support per i test plan che permette di indicare il numero di asserzioni e test che devono essere eseguiti all’interno del singolo test: in caso contrario il test fallirà;
test("top level test", (t) => {
  t.plan(2);
  t.assert.ok("some relevant assertion here");
  t.subtest("subtest", () => {});
});

20.15.1

Release di sicurezza.

20.16.0

  • aggiunta la funzione process.getBuiltinModule(id) che permette di caricare un modulo interno di Node.js. Questo permette di sviluppare dei moduli che devono supportare ambienti diversi da Node.js in modo più semplice;
  • aggiunto flag --allow-wasi per il supporto di WASI attraverso il permission model;

20.17.0

  • aggiunto il flag --experimental-require-module che permette il caricamento sincrono di moduli ES (non deve avere top level async-await);
  • aggiunta la funzione duplexPair() che implementa le DuplexPair API. Quando è invocata restituisce un array con due stream, ognuno connesso all’altro: quello che viene scritto in uno diventa disponibile nell’altro: const [ sideA, sideB ] = duplexPair();

20.18.0

La principale novità introdotta in questa versione è il supporto (experimental) al network inspector per Node.js.

Avviando Node.js con il flag --experimental-network-inspection diventa possibile collegare l’inspector di Chrome e fare debug delle richieste di rete.

La funzionalità è ancora in sviluppo ed è necessario che Chrome effettui dei cambiamenti. Intanto è possibile provarla usando:

node --inspect-wait --experimental-network-inspection -e "require('https').get('https://nodejs.org/en', (res) => { console.log(res.statusCode); })"
Debugger listening on ws://127.0.0.1:9229/<inspector-websocket-id>
For help, see: https://nodejs.org/en/docs/inspector

E poi aprire in Chrome l’URL devtools://devtools/bundled/inspector.html?ws=127.0.0.1:9229/<inspector-websocket-id> usando l’id del websocket mostrato nel terminale.

20.18.1

Release con aggiornamenti interni.

Date di rilascio delle versioni

CodiceData di Rilascio
20.0.018 aprile 2023
20.1.03 maggio 2023
20.2.016 maggio 2023
20.3.08 giugno 2023
20.3.120 giugno 2023
20.4.05 luglio 2023
20.5.018 luglio 2023
20.5.19 agosto 2023
20.6.04 settembre 2023
20.6.18 settembre 2023
20.7.018 settembre 2023
20.8.028 settembre 2023
20.8.15 ottobre 2023
20.9.024 ottobre 2023
20.10.022 novembre 2023
20.11.09 gennaio 2024
20.11.19 gennaio 2024
20.12.026 marzo 2024
20.12.126 marzo 2024
20.12.226 marzo 2024
20.13.07 maggio 2024
20.13.17 maggio 2024
20.14.028 maggio 2024
20.15.020 giugno 2024
20.15.120 giugno 2024
20.16.024 luglio 2024
20.17.021 agosto 2024
20.18.03 ottobre 2024
20.18.120 novembre 2024