Tehnologija
Node.js 25: što je stvarno novo, što se pokvarilo u ekosustavu i isplati li se nadograditi
Praktični pregled Node.js 25 (Current): V8 14.1 i performanse, Web Storage uključen po defaultu (što je srušilo testove/alate), permission model s --allow-net, portable module compile cache (sada stable), require(esm) označen kao stable, http.setGlobalProxyFromEnv(), fs.watch dobio ignore, i SEA se gradi u jednom koraku preko node --build-sea. Različite perspektive developera s linkovima + jasan zaključak: nadograditi odmah ili čekati LTS.

Prolog: nadogradiš Node — i odjednom “localStorage” sruši build
Postoje dvije vrste Node upgradea. Prva: “podižeš verziju i sve radi”. Druga: “podižeš verziju i backend odjednom baca browser-like greške”. Node.js 25 mnogima je donio ovaj drugi scenarij.
Docusaurus primjer je gotovo komičan: DOMException [SecurityError]: Cannot initialize local storage without a --localstorage-file path tijekom docusaurus build.[1] Slični simptomi pojavili su se i u CLI svijetu (Shopify) i u test runnerima (Jest/Vitest).[2][3][4]
Bitno: to nije “random bug u tvom repou”. To je posljedica činjenice da je Node 25 uključio Web Storage po defaultu, a localStorage u Nodeu nije 1:1 browser storage (file-backed, quota, shared ponašanje, bez enkripcije).[7][5]
Ipak, bilo bi pogrešno svesti Node 25 samo na Web Storage sagu. 25.4.0 i 25.5.0 donose zrele stvari (require(esm) stable, compile cache stable, --build-sea) koje realno poboljšavaju DX — ako ih uvodiš kontrolirano.[9][10][12]
Realni slučaj: docusaurus build pada na Node 25.x zbog localStorage SecurityError.[1]
Mini vremenska linija Node 25: zašto su 25.4 i 25.5 jednako bitni kao i “25.0.0”
Node 25 je Current linija (odd). Brzo se mijenja: prvo dođu novi defaulti, zatim ekosustav nađe edge-case, pa dođu stabilizacijska izdanja.[6]
• 25.0.0: V8 14.1, fokus na performanse, web API, permission model, Web Storage po defaultu.[8]
• 25.2.0: ispliva
localStorageregresija bez--localstorage-file(nodejs/node #60704) i udara po toolchainu.[5]• 25.4.0: require(esm) postaje stable, module compile cache postaje stable, dolaze ops stvarčice poput
http.setGlobalProxyFromEnv().[9]• 25.5.0: stiže
node --build-sea— SEA “u jednom koraku iz corea”, plus sitne ali bitne ops/monorepo promjene.[12]
Brza terminologija (da ne guglaš svake 2 minute)
Minimalni pojmovi za razumjeti Node 25 bez lutanja po flagovima.
• Current vs LTS: odd major = Current, even major = LTS. Node preporučuje production na Active/Maintenance LTS.[6]
• Web Storage u Nodeu:
localStorageje file-backed (--localstorage-file), nešifriran, quota 10MB, i shared u server procesu.[7]• Permission Model: procesni permisije (
--permission,--allow-net,--allow-fs-read) kao “sigurnosni pojas”. Nije sandbox i nema garancija protiv malicious code.[11]• require(esm): most između CJS i ESM. 25.4.0 ga označava kao stable (mijenja strategiju migracije).[9]
• Module compile cache: on-disk code cache za bržu kompilaciju modula, s
portablenačinom.[10]• SEA: single executable applications. 25.5.0 sve olakšava s
--build-sea.[12][13]• Ops QoL: proxy iz env (
http.setGlobalProxyFromEnv()), ignore u watcherima (fs.watch({ ignore: ... })).[14][15]
Node 25.0.0: što je novo u osnovi i gdje je praktična vrijednost
25.0.0 je temelj: V8 14.1, performance radovi, web API i čišćenje legacyja. Prava “zrelost” se vidi u 25.4/25.5.[8][9][12]
Web Storage
Default promjena koja je uzrokovala regresije u ekosustavu (tools/tests/CLI).[8][5][4]
Security posture
Permissions u “secure-by-default” priči, ali s jasnim ograničenjima (nije sandbox).[11]
Legacy cleanup
Major izdanja često bole zbog uklanjanja deprecated API-ja (SlowBuffer).[16]
Vizualni marker početka: Node.js 25.0.0 (Current).[8]
Section node-25-0 screenshotWeb Storage po defaultu: zašto je eksplodiralo i kako izgleda u stvarnim projektima
Problem nije da je Web Storage “loš”. Problem je što se promijenio default, pa tooling počne izvršavati grane koda koje nikad nisu testirane server-side.
nodejs/node #60704 opisuje regresiju 25.2.0: “Cannot initialize local storage without a --localstorage-file path”, i referencira puknute toolchaine (webpack/jest/html-webpack-plugin).[5]
Vitest #8757 pokazuje drugi tip faila: u Node 25 localStorage više nije undefined, što može srušiti mockove u test okruženju.[4] Jest #15888 dodaje još jedan realni primjer: test runner pada s SecurityError na Node 25.2.0.[3]
Brzi workaround (ako ti storage ne treba): privremeno isključi Web Storage flagom iz docs.[7]
Pouka za timove: čak i ako “ne koristite localStorage”, vaše dependencije možda koriste. Držati Current u CI matrici ima smisla kao early warning.[6]
nodejs/node #60704: regresija 25.2.0 — localStorage bez --localstorage-file može rušiti buildove.[5]
Vitest #8757: Web Storage default može rušiti testove zbog promijenjenih očekivanja oko localStorage.[4]
Jest #15888: test runner pada s SecurityError na Node 25.2.0.[3]
Node 25.4.0: require(esm) postaje stable (i to mijenja migracije)
Ovo je tip promjene koja ne napravi headline, ali ti može uštedjeti tjedne u repoima gdje CJS i ESM moraju koegzistirati.
1) Zašto je bitno
2) Praktični pattern: adapter za default export
const pkg = require('some-esm-only-package');
const api = pkg?.default ?? pkg;
module.exports = api;Ovo je standardan način rada s namespace objektom kad ESM daje default export.[22]
3) Signal za timove
Stabilizacija u Current liniji priprema teren za šire usvajanje. LTS+Current u CI daje benefit bez prod rizika.[6]
Vizualni marker stabilizacije: Node.js 25.4.0 (Current).[9]
Section require-esm screenshotModule compile cache: portable mod i jasna dokumentacija — što to daje u CI/containere
Compile cache je optimizacija. Najviše pomaže kad imaš puno cold startova ili velik modul graph (tools, CLI, workeri).
node:module docs imaju vrlo praktičan dio o portabilnosti: ako se mijenjaju absolute paths, cache može izgubiti učinkovitost; portable pomaže u više scenarija.[10]
Minimalni primjer:
import module from 'node:module';
module.enableCompileCache({ directory: '.node-compile-cache', portable: true });U CI-u smisleno je eksplicitno upravljati cache direktorijem da preživi između runova.
Docs: portabilnost compile cachea + portable način s API/env primjerima.[10]
Node 25.5.0: `node --build-sea` pretvara SEA u “jedan korak”
Ovo je jedna od naj“product” promjena: single executable više ne izgleda kao ritual s eksternim injectorom.
1) Osnovna ideja
2) Praktika
Za CLI/agente: manje dependencija i manje krhkih release koraka. Ali testiraj na target OS/shellovima (postoji Windows Command Prompt issue).[21]
3) Savjet timu
SEA je alat za distribuciju, ne sigurnosni model. I dalje održavaj dependencije i supply chain. Current u CI-u ostaje early warning.[6]
25.5.0: sekcija o --build-sea i primjer komandi u službenim release notes.[12]
Ops QoL: proxy iz env — čist put za enterprise mreže
Nije headline, ali smanjuje količinu “sitnih custom wrappera” u projektima s korporativnim CI.
Minimalno:
import http from 'node:http';
const restore = http.setGlobalProxyFromEnv();
// restore();API
Korisno kad se proxy konfigurira preko env varijabli (CI/enterprise).[14]
Rezultat
Manje šanse da svaki HTTP klijent bude drugačije konfiguriran.
Docs: http.setGlobalProxyFromEnv([proxyEnv]) + built-in proxy support sekcija.[14]
Monorepo problem: `fs.watch({ ignore })` za manje buke i opterećenja
U velikim repoima watcheri znaju biti pakao (node_modules, .git, generirani output). Docs opisuju ignore kao opciju (glob/RegExp/function/array).[15]
Minimalni primjer:
import { watch } from 'node:fs';
watch('.', {
recursive: true,
ignore: ['**/node_modules/**', '**/.git/**'],
}, () => {});Breaking changes: Node 25 ruši dependencije zbog “legacy cleanup” (ne novih featurea)
Major izdanja često bole zbog finalizacije deprecations. SlowBuffer je dobar primjer.[16]
1) Što se dogodilo sa SlowBuffer
Node deprecations docs kaže da je SlowBuffer uklonjen i preporuča Buffer.allocUnsafeSlow(size).[16]
2) Kako izgleda u stvarnosti
Postoji realan slučaj: backend crash na Node 25.x zbog dependency chaina koji dira SlowBuffer.prototype.[17]
3) Brzi scan prije upgradea
rg -n "\bSlowBuffer\b" .Pa pnpm why / npm ls da pronađeš legacy lanac.
Upgrade playbook: kako uvesti Node 25 da donese vrijednost (ne bol)
Kratka, praktična checklist-a za timove.
• 1) Prod na LTS, Node 25 u CI (LTS + Current matrica).[6]
• 2) Pokreni testove s isključenim Web Storage da brzo izoliraš problem:
NODE_OPTIONS="--no-experimental-webstorage".[7]• 3) Ako pukne — pogledaj gdje je već puklo: nodejs/node #60704, Vitest #8757, Jest #15888.[5][4][3]
• 4) Feature iz 25.4/25.5 uvodi prvo izolirano (CLI/worker), ne “odmah u prod runtime”.[9][12]
• 5) Monorepo: podesi watchere:
fs.watch({ ignore })smanjuje load.[15]• 6) Corporate CI: probaj
http.setGlobalProxyFromEnv()kao jednostavan globalni pristup.[14]
Zaključak: treba li odmah prijeći na Node.js 25?
Bez ideologije: Node 25 je odličan kao CI “detektor” i koristan za CLI/agente. Za produkcijski backend LTS često pobjeđuje zbog stabilnosti.
Produkcijski backend
Node preporučuje production na Active/Maintenance LTS.[6]
CI / kompatibilnost
Node 25 otkriva regresije (Web Storage) i legacy cleanup (SlowBuffer) rano, bez prod incidenta.[5][16]
CLI / agenti
--build-sea (25.5.0) + zrelost 25.4.0 su realni DX winovi. Testiraj target OS/shell.[12][21]
Mindset
Current postoji da se ekosustav prilagodi. Ako te boli — drži u CI, prod na LTS.[6]
Sources
Izvori po redoslijedu pojavljivanja (pozicija = [n]).
• Docusaurus issue #11545: build broken on Node 25.2.0 due to localStorage SecurityError Pročitaj izvor ↗
• Shopify community: shopify-cli fails on Node 25.2.0 due to localStorage SecurityError Pročitaj izvor ↗
• Jest issue #15888: Jest fails with localStorage error on Node 25.2.0 Pročitaj izvor ↗
• Vitest issue #8757: Node v25 breaks tests with Web Storage API Pročitaj izvor ↗
• nodejs/node issue #60704: Regression 25.2.0 — Cannot initialize local storage without --localstorage-file path Pročitaj izvor ↗
• Node.js Releases: Current vs LTS policy (production guidance) Pročitaj izvor ↗
• Node.js Globals docs: Web Storage semantics + disable flag Pročitaj izvor ↗
• Node.js 25.0.0 release notes (V8 14.1, Web Storage default, performance highlights) Pročitaj izvor ↗
• Node.js 25.4.0 release notes (require(esm) stable, compile cache stable, ops improvements) Pročitaj izvor ↗
• Node.js node:module docs: module compile cache + portability Pročitaj izvor ↗
• Node.js Permissions docs: seat belt approach (not a sandbox) Pročitaj izvor ↗
• Node.js 25.5.0 release notes (--build-sea, other notable changes) Pročitaj izvor ↗
• Node.js Single Executable Applications docs (--build-sea flow and config) Pročitaj izvor ↗
• Node.js HTTP docs: http.setGlobalProxyFromEnv() Pročitaj izvor ↗
• Node.js Deprecations docs: SlowBuffer removed + migration note Pročitaj izvor ↗
• twentyhq/twenty issue: crash on Node 25 due to SlowBuffer removal via dependency chain Pročitaj izvor ↗
• nodejs/Release issue #1113: cadence discussion (annual majors / LTS duration) Pročitaj izvor ↗
• nodejs/node issue: --build-sea fails in Windows Command Prompt (shell-specific behavior) Pročitaj izvor ↗
• Joyee Cheung: require(esm) in Node.js — from experiment to stability Pročitaj izvor ↗
• Joyee Cheung: Improving SEA building (why build moved into Node.js core) Pročitaj izvor ↗
ČPP
Ne. To je Current (odd major). Node eksplicitno kaže da production aplikacije trebaju koristiti Active ili Maintenance LTS.[6]
Jer se promijenio default. `localStorage` je dostupan bez experimental flaga, ali Node semantika je drugačija (file, 10MB, shared). Tooling pretpostavke su pukle.[7][5][4]
Privremeno isključi Web Storage s `NODE_OPTIONS="--no-experimental-webstorage"` ili runtime flagom. To je dokumentirano u globals docs i spominje se kao workaround.[7][5]
Da, ali testiraj na target OS/shell. Postoji Windows Command Prompt specifičan issue.[21] Detalji su u SEA docs.[13]
U jednoj rečenici: uzmi vrijednost Node 25 bez da uzmeš njegov prod rizik
Najzdravija strategija: prod na LTS, Node 25 u CI kao rani detektor regresija, a 25.4/25.5 feature (require(esm), compile cache, build-sea) prvo uvoditi u izolirane eksperimente (CLI/worker). DX gore, rizik dolje.