PAS7 Studio

Tecnologia

Node.js 25: cosa c’è davvero di nuovo, cosa si è rotto nell’ecosistema e se conviene aggiornare

Recensione “dal mondo reale” di Node.js 25 (Current): V8 14.1 e performance, Web Storage abilitato di default (con rotture su test/tooling), permission model con --allow-net, module compile cache portabile (ora stabile), require(esm) marcato stabile, http.setGlobalProxyFromEnv(), fs.watch con ignore, e SEA costruibile in un solo step con node --build-sea. Punti di vista di developer con link + verdetto chiaro: aggiornare ora o aspettare LTS.

Node.js 25 — cambiamenti, reazioni degli sviluppatori e decisione se aggiornare

Prologo: aggiorni Node — e all’improvviso “localStorage” fa saltare la build

Ci sono due tipi di upgrade Node. Il primo è “alzo la versione, tutto ok”. Il secondo è “alzo la versione e ora il backend mi spara errori da browser”. Node.js 25 ha fatto vivere a molti team il secondo scenario.

Con Docusaurus sembra surreale: DOMException [SecurityError]: Cannot initialize local storage without a --localstorage-file path durante docusaurus build.[1] Sintomi simili compaiono anche nel mondo CLI (Shopify) e nei test runner (Jest/Vitest).[2][3][4]

Qui il punto è: non è un “bug random nel tuo repo”. È una conseguenza del fatto che Node 25 ha abilitato Web Storage di default, ma localStorage su Node non è identico al browser (file-backed, quota, comportamento shared, niente cifratura).[7][5]

Eppure sarebbe un errore ridurre Node 25 alla saga di Web Storage. 25.4.0 e 25.5.0 portano miglioramenti maturi (require(esm) stabile, compile cache stabile, --build-sea) che riducono il dolore delle migrazioni e migliorano DX — se li adotti in modo controllato.[9][10][12]

Caso reale: docusaurus build fallisce su Node 25.x per localStorage SecurityError.[1]

Section prologue screenshot

Mini-cronologia di Node 25: perché contano anche 25.4 e 25.5 (non solo “25.0.0”)

Node 25 è una linea Current (odd). Si muove veloce: prima arrivano nuovi default, poi l’ecosistema trova edge case, poi escono release di stabilizzazione.[6]

  • 25.0.0: V8 14.1, focus performance, web API, permission model, Web Storage abilitato di default.[8]

  • 25.2.0: emerge la regressione localStorage senza --localstorage-file (nodejs/node #60704) che colpisce toolchain.[5]

  • 25.4.0: require(esm) diventa stabile, module compile cache diventa stabile, arrivano “ops goodies” come http.setGlobalProxyFromEnv().[9]

  • 25.5.0: arriva node --build-sea — SEA “un solo step dal core”, più piccole ma utili modifiche ops/monorepo.[12]

Terminologia rapida (così non devi googlare ogni 2 minuti)

Solo i concetti indispensabili per capire Node 25 senza perdersi nei flag.

  • Current vs LTS: odd major = Current, even major = LTS. Node raccomanda esplicitamente Active/Maintenance LTS per production.[6]

  • Web Storage in Node: localStorage su Node è file-backed (--localstorage-file), non cifrato, con quota 10MB, e shared nel processo server.[7]

  • Permission Model: permessi di processo (--permission, --allow-net, --allow-fs-read) come “cintura”. Non è un sandbox e non protegge da malicious code.[11]

  • require(esm): ponte tra CJS ed ESM. 25.4.0 segna il meccanismo come stabile (cambia la strategia di migrazione).[9]

  • Module compile cache: code cache su disco per accelerare la compilazione del grafo moduli, con modalità portable.[10]

  • SEA: single executable applications. In 25.5.0 diventa molto più semplice con --build-sea.[12][13]

  • Ops QoL: proxy da env (http.setGlobalProxyFromEnv()), ignore nei watcher (fs.watch({ ignore: ... })).[14][15]

Node 25.0.0: cosa cambia “alla base” e dove sta la utilità pratica

25.0.0 è la base: V8 14.1, performance, web API e pulizia legacy. La vera “maturità” si vede in 25.4/25.5.[8][9][12]

V8

14.1

Le note 25.0.0 evidenziano miglioramenti performance, inclusi su JSON.stringify.[8]

Web Storage

abilitato di default

Cambio di default che ha causato regressioni nell’ecosistema (tool/test/CLI).[8][5][4]

Security posture

permissions

Permissions come parte “secure-by-default”, con limiti chiari (non sandbox).[11]

Legacy cleanup

deprecations

I major release spesso fanno male per rimozioni di API deprecated (SlowBuffer).[16]

Segnale visivo dell’inizio linea: Node.js 25.0.0 (Current).[8]

Section node-25-0 screenshot

Web Storage di default: perché ha “esploso” e come appare nei progetti reali

Il problema non è che Web Storage sia “cattivo”. Il problema è che è cambiato il default, e parte del tooling ha iniziato a eseguire rami non testati su server.

nodejs/node #60704 descrive la regressione 25.2.0: “Cannot initialize local storage without a --localstorage-file path”, e collega toolchain rotti (webpack/jest/html-webpack-plugin).[5]

Vitest #8757 mostra un altro failure mode: in Node 25 localStorage non è più undefined e questo può rompere i mock.[4] Jest #15888 aggiunge un altro caso: test runner che fallisce con SecurityError su Node 25.2.0.[3]

Workaround rapido (se non ti serve): disabilitare temporaneamente Web Storage con il flag documentato nelle globals docs.[7]

Lezione per i team: anche se “non usi localStorage”, le dipendenze potrebbero farlo. Tenere Current in CI è un modo sano per intercettare sorprese.[6]

nodejs/node #60704: regressione 25.2.0 — localStorage senza --localstorage-file può far fallire la build.[5]

Section webstorage-saga screenshot

Vitest #8757: Web Storage abilitato di default può rompere i test per via delle nuove aspettative su localStorage.[4]

Section webstorage-saga screenshot

Jest #15888: fallimento con SecurityError su Node 25.2.0.[3]

Section webstorage-saga screenshot

Node 25.4.0: require(esm) diventa stabile (e cambia la migrazione)

Una di quelle modifiche che non fa rumore, ma ti salva settimane in repo dove CJS ed ESM devono convivere.

1) Perché conta

Con più pacchetti ESM-only, i progetti CJS incontrano spesso ERR_REQUIRE_ESM. Un ponte più maturo permette migrazioni progressive invece di un “big bang”.[9][22]

2) Pattern pratico: adattatore per default export

JS
const pkg = require('some-esm-only-package');
const api = pkg?.default ?? pkg;

module.exports = api;

È un modo standard per gestire il namespace object quando ESM espone un default export.[22]

3) Cosa significa per i team

Stabilizzare in Current prepara la strada all’ecosistema. LTS+Current in CI ti fa prendere valore senza rischio prod.[6]

Marker visivo della fase “stabilizzazione”: Node.js 25.4.0 (Current).[9]

Section require-esm screenshot

Module compile cache: modalità portable e documentazione più chiara — cosa dà in CI/container

La compile cache è un’ottimizzazione. È utile dove hai molti cold start o un grafo moduli grande (tool, CLI, worker).

Le docs node:module hanno una sezione concreta sulla portabilità: se cambiano gli absolute path, l’efficacia può scendere; portable aiuta a riusare la cache in più scenari.[10]

Esempio minimo:

JS
import module from 'node:module';

module.enableCompileCache({ directory: '.node-compile-cache', portable: true });

In CI, gestisci esplicitamente la directory cache per non perderla tra i run.

Docs: sezione sulla portabilità + modalità portable con esempi API/env.[10]

Section compile-cache screenshot

Node 25.5.0: `node --build-sea` rende SEA un workflow “in un solo step”

Una delle modifiche più “product”: costruire un single executable non sembra più un rituale con injector esterno.

1) Idea base

25.5.0 introduce --build-sea e consolida i passi SEA in un singolo step disponibile dal core.[12][13]

BASH
echo 'console.log("Hello")' > hello.js
echo '{ "main": "hello.js", "output": "sea" }' > sea-config.json
node --build-sea sea-config.json
./sea

2) Takeaway pratico

Per CLI/agenti: meno dipendenze e meno step fragili. Ma testa su OS/shell target (ci sono segnalazioni su Windows Command Prompt).[21]

3) Consiglio team

SEA è per la distribuzione, non sostituisce un modello di sicurezza. Continua a curare dipendenze e supply chain. Tieni Current in CI per intercettare sorprese.[6]

25.5.0: sezione --build-sea con esempio comandi nelle release notes ufficiali.[12]

Section sea-build-sea screenshot

Ops QoL: proxy da env e un percorso pulito per reti enterprise

Non è una headline feature, ma riduce “micro wrapper” custom nei progetti con CI aziendale dietro proxy.

Snippet minimo:

JS
import http from 'node:http';

const restore = http.setGlobalProxyFromEnv();
// restore();

API

http.setGlobalProxyFromEnv()

Utile quando il proxy è configurato via env (CI/reti enterprise).[14]

Tip

chiamalo all’avvio

Evita chiamate nel mezzo delle request; fallo nel bootstrap di service/CLI.[14]

Risultato

più coerente

Meno probabilità che ogni client HTTP venga configurato in modo diverso.

Docs: http.setGlobalProxyFromEnv([proxyEnv]) + sezione built-in proxy support.[14]

Section ops-qol screenshot

Dolore monorepo: `fs.watch({ ignore })` per ridurre rumore e carico

In repo grandi, i watcher diventano un problema (node_modules, .git, output generati). Le docs descrivono ignore come opzione che accetta glob/RegExp/function/array.[15]

Esempio minimo:

JS
import { watch } from 'node:fs';

watch('.', {
  recursive: true,
  ignore: ['**/node_modules/**', '**/.git/**'],
}, () => {});

Breaking changes: Node 25 rompe dipendenze con “legacy cleanup” (non con nuove feature)

I major release spesso fanno male per finalizzazione deprecations. SlowBuffer è l’esempio perfetto.[16]

1) Cosa è successo a SlowBuffer

Le deprecations docs indicano che SlowBuffer è stato rimosso e suggeriscono Buffer.allocUnsafeSlow(size).[16]

2) Come appare in produzione

C’è un caso reale: backend che crasha su Node 25.x perché una dependency chain tocca SlowBuffer.prototype.[17]

3) Quick scan prima dell’upgrade

BASH
rg -n "\bSlowBuffer\b" .

Poi pnpm why / npm ls per trovare la catena legacy.

Upgrade playbook: come adottare Node 25 per valore (non per dolore)

Una checklist breve e realistica per i team.

  • 1) Prod su LTS, Node 25 in CI (matrice LTS + Current).[6]

  • 2) Esegui i test con Web Storage disabilitato per isolare velocemente: NODE_OPTIONS="--no-experimental-webstorage".[7]

  • 3) Se si è rotto, guarda dove si è rotto già: nodejs/node #60704, Vitest #8757, Jest #15888.[5][4][3]

  • 4) Se ti interessano le feature 25.4/25.5, provale prima in un esperimento separato (CLI/worker), non in prod “in un colpo”.[9][12]

  • 5) Per monorepo, aggiusta i watcher: fs.watch({ ignore }) riduce rumore e load.[15]

  • 6) Per CI dietro proxy, prova http.setGlobalProxyFromEnv() come soluzione globale semplice.[14]

Verdetto: conviene aggiornare a Node.js 25 adesso?

Niente ideologia: Node 25 è ottimo come “detector” in CI, ed è utile per alcuni prodotti (CLI/agenti). Per i backend in produzione, LTS spesso vince per stabilità.

Backend in produzione

Meglio aspettare / restare su LTS

Node raccomanda Active/Maintenance LTS per production.[6]

CI / compatibilità

Aggiungilo ora

Node 25 fa emergere regressioni (Web Storage) e cleanup legacy (SlowBuffer) senza rischio incidenti in prod.[5][16]

CLI / agenti

Upgrade sensato

--build-sea (25.5.0) + maturità 25.4.0 sono un vero boost DX. Testa su OS/shell target.[12][21]

Mentalità

Current può “mordere”

Current esiste per far adattare l’ecosistema. Se rompe la giornata, tienilo in CI e lascia prod su LTS.[6]

Sources

Fonti in ordine di apparizione (posizione in lista = numero [n]).

FAQ

Node.js 25 è una release LTS?

No. È Current (odd major). Node dice chiaramente che in production dovresti usare Active o Maintenance LTS.[6]

Perché Web Storage ha fatto così tanto rumore?

Perché è cambiato il default. `localStorage` è diventato disponibile senza flag sperimentali, ma su Node la semantica è diversa (file, 10MB, shared). Il tooling ha rotto assunzioni.[7][5][4]

Come sbloccare CI velocemente se localStorage rompe tutto?

Disabilita temporaneamente Web Storage con `NODE_OPTIONS="--no-experimental-webstorage"` o tramite flag runtime. È documentato nelle globals e citato come workaround.[7][5]

SEA con --build-sea è già usabile?

Sì, ma testa su OS/shell target. C’è un issue specifico su Windows Command Prompt.[21] Per dettagli vedi le SEA docs.[13]

In una frase: prendi il valore di Node 25 senza portarti il rischio in prod

Strategia più sana: prod su LTS, Node 25 in CI come detector di regressioni, e adozione graduale delle feature 25.4/25.5 (require(esm), compile cache, build-sea) in esperimenti isolati (CLI/worker). DX su, rischio giù.

Articoli correlati

Scopri altri articoli utili

growthFebruary 15, 2026

AI SEO / GEO nel 2026: i tuoi prossimi clienti non sono umani — sono agenti

La ricerca sta passando dai click alle risposte. Bot e agenti AI scansionano, citano, raccomandano e sempre più spesso acquistano. Scopri cosa significa AI SEO / GEO, perché la SEO classica non basta più e come PAS7 Studio aiuta i brand a vincere visibilità nel web “agentico”.

Leggere →
telegram-media-saverJanuary 8, 2025

Tag automatici e ricerca per link salvati

Integra con GDrive/S3/Notion per tag automatici e ricerca veloce tramite API di ricerca

Leggere →
servicesJanuary 1, 2025

Sviluppo di bot e servizi di automazione

Sviluppo professionale di bot Telegram e automazione dei processi aziendali: chatbot, assistenti AI, integrazioni CRM, automazione dei flussi di lavoro.

Leggere →
backend-engineeringFebruary 15, 2026

Bun vs Node.js nel 2026: perché Bun sembra più veloce (e come valutare l’app prima di migrare)

Bun è un toolkit JavaScript all-in-one più rapido: runtime, package manager, bundler e test runner. Qui trovi cosa è reale (con benchmark), cosa può rompersi e come ottenere un audit di readiness gratuito con @pas7-studio/bun-ready.

Leggere →

Sviluppo professionale per la tua attività

Creiamo soluzioni web moderne e bot per le aziende. Scopri come possiamo aiutarti a raggiungere i tuoi obiettivi.