Node.js 25: що нового насправді, що зламалось в екосистемі, і чи варто оновлюватись
Живий розбір Node.js 25 (Current) з історіями з реального світу: V8 14.1 і перформанс, Web Storage увімкнули за замовчуванням (і це зламало тести/тулзи), permission model з --allow-net, portable compile cache (тепер stable), require(esm) став stable, http.setGlobalProxyFromEnv(), fs.watch отримав ignore, і SEA тепер збирається однією командою через node --build-sea. Думки розробників з лінками + чіткий висновок: апгрейдити чи чекати LTS.

Є два типи апгрейду Node. Перший — «підняли версію, все ок». Другий — «підняли версію, а наш проєкт тепер видає браузерні помилки на бекенді». Node.js 25 багатьом запам’ятався другим типом.
Кейс Docusaurus виглядав максимально сюрреалістично: DOMException [SecurityError]: Cannot initialize local storage without a --localstorage-file path — під час docusaurus build.[1] Аналогічні симптоми ловили і в CLI-світі (Shopify), і в тест-раннерах (Jest/Vitest).[2][3][4]
Це важливо: це не «рандомний баг у вашому репо». Це наслідок того, що Node 25 ввімкнув Web Storage за замовчуванням, а localStorage у Node — це не браузерний storage 1:1 (файл, квота, shared-поведінка, відсутність шифрування).[7][5]
І разом з цим у Node 25 є великий плюс: 25.4.0 і 25.5.0 принесли зрілі фічі (require(esm) stable, compile cache stable, --build-sea), які реально зменшують міграційний біль і покращують DX — але їх треба брати з розумом.[9][10][12]
Реальний кейс: docusaurus build падає на Node 25.x через localStorage SecurityError.[1]
Node 25 — це Current-лінія (odd). Вона живе швидко: спершу «включили нові дефолти», потім екосистема знаходить edge-cases, потім виходять стабілізаційні релізи.[6]
• 25.0.0: V8 14.1, акцент на перформанс, web-API, permission model, включення Web Storage by default.[8]
• 25.2.0: на поверхню вилізла регресія
localStorageбез--localstorage-file(nodejs/node #60704), яка зачепила тулінг-ланцюжки.[5]• 25.4.0: require(esm) стає stable, module compile cache стає stable, додають ops-плюшки на кшталт
http.setGlobalProxyFromEnv().[9]• 25.5.0: з’являється
node --build-sea— SEA «в один крок» із core, плюс дрібні, але важливі зміни для ops/monorepo.[12]
Мінімум понять, без яких Node 25 читається як набір випадкових флагів і regression-тредів.
• Current vs LTS: odd major = Current, even major = LTS-лінія. Node прямо рекомендує production тримати на Active/Maintenance LTS.[6]
• Web Storage у Node:
localStorageу Node — файл-базований storage (--localstorage-file), незашифрований, квота 10MB, і в серверному процесі він shared.[7]• Permission Model: дозволи процеса (
--permission,--allow-net,--allow-fs-read) як «ремінь безпеки». Це не sandbox і не дає гарантій проти malicious code.[11]• require(esm): міст між CJS і ESM. Node 25.4.0 зафіксував стабільність механізму (і це впливає на міграції).[9]
• Module compile cache: on-disk code cache для пришвидшення компіляції модульного графа, з
portableрежимом.[10]• SEA: single executable applications. У 25.5.0 це стало значно простіше через
--build-sea.[12][13]• Ops QoL: проксі з env (
http.setGlobalProxyFromEnv()), ігнор у вотчерах (fs.watch({ ignore: ... })).[14][15]
25.0.0 — це фундамент: V8 14.1, перформансні штуки, web-API, і підчищення legacy. Але справжня “зрілість” лінійки відчувається в 25.4/25.5.[8][9][12]
14.1
Реліз-ноти 25.0.0 підкреслюють перформансні покращення, зокрема на JSON.stringify.[8]
enabled by default
Смілива default-зміна, яка дала хвилю регресій в екосистемі (тулінг/тести/CLI).[8][5][4]
permissions
Permission model у фокусі «secure-by-default» підходу, але з чіткими обмеженнями (не sandbox).[11]
deprecations
Major-релізи часто болять не через фічі, а через прибирання deprecated API (приклад — SlowBuffer).[16]
Візуальний маркер початку лінійки: Node.js 25.0.0 (Current).[8]
Скріншот секції node-25-0Проблема не в тому, що Web Storage — погана ідея. Проблема в тому, що змінилася default-поведінка, і частина тулінгу/бібліотек почала виконувати гілки коду, які ніколи не тестувалися на сервері.
nodejs/node #60704 прямо описує регресію 25.2.0: «Cannot initialize local storage without a --localstorage-file path». І важливий момент: issue посилається на зламані ланцюжки webpack/jest/html-webpack-plugin.[5]
Vitest issue #8757 показує інший тип поломки: у Node 25 localStorage перестає бути undefined, і це може “збити” моки у тестових середовищах.[4] Jest issue #15888 — ще один доказ, що це не поодинокий кейс: тест-раннер падає з SecurityError на Node 25.2.0.[3]
Швидкий антикризовий workaround (коли storage вам не потрібен) — тимчасово вимкнути web storage флагом, який описаний у docs.[7]
Ключова думка для команд: навіть якщо ви «не використовуєте localStorage», ваші залежності можуть робити це опосередковано. Тому Current-лінію логічно тримати в CI-матриці як ранній детектор таких сюрпризів.[6]
nodejs/node #60704: регресія 25.2.0 — localStorage без --localstorage-file провокує падіння.[5]
Vitest #8757: Node v25 вмикає Web Storage, і тести можуть ламатися через зміну очікувань щодо localStorage.[4]
Jest #15888: тест-раннер падає з SecurityError на Node 25.2.0.[3]
Це той клас змін, який не «кричить» у реліз-нотах, але економить тижні в репозиторіях, де CJS і ESM змушені співіснувати.
1) Чому це важливо
2) Практичний патерн: адаптер під default export
const pkg = require('some-esm-only-package');
const api = pkg?.default ?? pkg;
module.exports = api;Це не “хак”. Це типовий спосіб працювати з namespace-object, коли ESM експортує default.[22]
3) Сигнал для великих команд
Стабілізація в Current-лінії — це підготовка до того, що з часом поведінка стане звичною і для LTS-світу. Тому CI-матриця (LTS+Current) тут — найздоровіший спосіб забрати користь без ризику інцидентів.[6]
Візуальний маркер “стабілізаційного” релізу: Node.js 25.4.0 (Current).[9]
Скріншот секції require-esmCompile cache — це оптимізація, яка найкраще працює там, де у вас багато холодних стартів або великий модульний граф (особливо інструменти, CLI, воркери).
У доках node:module є дуже практичний розділ про переносимість: якщо змінюються absolute paths, кеш може втратити ефективність; portable режим дозволяє reuse у більшій кількості сценаріїв.[10]
Мінімальний приклад, який зазвичай достатній для експерименту:
import module from 'node:module';
module.enableCompileCache({ directory: '.node-compile-cache', portable: true });Якщо ви це тестуєте в CI, варто керувати директорією кешу явно (щоб не «випаровувався» між прогонами).
Docs: “Portability of the compile cache” + portable режим і env-приклад.[10]
Це одна з найбільш «продуктових» змін лінійки: тепер збірка single-executable не виглядає як ритуал з зовнішнім інжектором.
1) Базова ідея
2) Практичний висновок
Для CLI/локальних агентів це означає менше залежностей і менше “крихких” кроків у release pipeline. Але як і все кросплатформене — тестуйте на цільових OS/шелах (є окремі репорти про Windows Command Prompt нюанси).[21]
3) Порада для команд
SEA — це інструмент дистрибуції, не заміна security-моделі. Не підмінюйте ним оновлення залежностей/перевірку supply chain. І тримайте CI-матрицю, бо саме вона ловить сюрпризи Current-ліній.[6]
Реліз 25.5.0: блок про --build-sea і приклад команд прямо в нотатках релізу.[12]
Це той тип змін, який не потрапляє в заголовки, але реально зменшує кількість «дрібних кастомних обгорток» у проєктах з корпоративним CI.
Мінімальний приклад:
import http from 'node:http';
const restore = http.setGlobalProxyFromEnv();
// restore();http.setGlobalProxyFromEnv()
Зручно для середовищ, де проксі керується через env (CI/enterprise networks).[14]
викликати на старті
Уникайте виклику “посеред запитів”; робіть це на bootstrap етапі сервісу/CLI.[14]
передбачуваніше
Менше шансів, що кожен HTTP-клієнт буде налаштований по-своєму.
Docs: http.setGlobalProxyFromEnv([proxyEnv]) + секція про built-in proxy support.[14]
Якщо у вас великий репозиторій, вотчери — це окремий світ болю (node_modules, .git, генеровані директорії). Node 25.5.0 згадує доповнення до fs.watch, а docs описують ignore як опцію, яка може приймати glob/RegExp/function/array.[15]
Мінімальний приклад для dev-інструментів:
import { watch } from 'node:fs';
watch('.', {
recursive: true,
ignore: ['**/node_modules/**', '**/.git/**'],
}, () => {});У major-релізах Node часто боляче не через нові API, а через фіналізацію деprecation. SlowBuffer — показовий приклад такого прибирання.[16]
1) Що сталося з SlowBuffer
В deprecations docs Node прямо зазначено, що SlowBuffer прибрано і треба переходити на Buffer.allocUnsafeSlow(size).[16]
2) Як це виглядає “в полі”
Є реальний кейс, де бекенд падав на Node 25.x через dependency chain, який торкався SlowBuffer.prototype.[17]
3) Швидкий scan перед апгрейдом
rg -n "\bSlowBuffer\b" .Потім pnpm why/npm ls, щоб знайти, хто тягне legacy-залежність.
Це короткий «бойовий» чекліст, який реально працює в командах.
• 1) Тримай прод на LTS, а Node 25 додай у CI (матриця LTS + Current).[6]
• 2) Проганяй тести з вимкненим Web Storage, щоб швидко локалізувати проблеми:
NODE_OPTIONS="--no-experimental-webstorage".[7]• 3) Якщо зламалося — дивись туди, де вже зламалось у інших: nodejs/node #60704, Vitest #8757, Jest #15888.[5][4][3]
• 4) Якщо тебе цікавлять фічі 25.4/25.5, винось їх у окремий експеримент (CLI/воркер), не в прод-бекенд “одним махом”.[9][12]
• 5) Для monorepo підкрути вотчери:
fs.watch({ ignore })знижує шум і навантаження.[15]• 6) Для корпоративного CI за проксі: спробуй
http.setGlobalProxyFromEnv()як просте глобальне рішення.[14]
Вердикт без фанатизму: Node 25 — дуже корисний як «індикатор майбутніх проблем» (CI), і корисний для окремих продуктів (CLI/агенти). Але для прод-бекенду LTS часто виграє саме стабільністю.
Скоріше чекати / LTS
Node рекомендує production тримати на Active/Maintenance LTS.[6]
Додати вже
Node 25 швидко покаже регресії залежностей (Web Storage) і legacy cleanup (SlowBuffer), без ризику інциденту в проді.[5][16]
Можна апгрейдити
--build-sea (25.5.0) + дозрівання 25.4.0 — це реальний DX-профіт. Просто тестуйте на target OS/шелах.[12][21]
Current має право «кусатися»
Current існує, щоб екосистема встигла адаптуватися. Якщо він ламає день — тримайте його в CI, а прод залишайте на LTS.[6]
Ні. Це Current (odd major). Node прямо пише, що production застосунки мають використовувати Active або Maintenance LTS.[6]
Бо змінилася default-поведінка. `localStorage` став доступний без experimental-флага, а в Node він має іншу семантику (файл, 10MB, shared). Це зламало припущення тулінгу/тестів.[7][5][4]
Тимчасово вимкнути Web Storage через `NODE_OPTIONS="--no-experimental-webstorage"` або як флаг запуску. Це згадується в globals docs і фігурує в regression-тредах як workaround.[7][5]
Так, але тестуйте на цільових OS/шелах. Є shell-specific issue на Windows Command Prompt.[21] Деталі конфігів і процесу — в SEA docs.[13]
Джерела в порядку появи у тексті (позиція в списку = номер [n]).
• Docusaurus issue #11545: build broken on Node 25.2.0 due to localStorage SecurityError
• Shopify community: shopify-cli fails on Node 25.2.0 due to localStorage SecurityError
• Jest issue #15888: Jest fails with localStorage error on Node 25.2.0
• Vitest issue #8757: Node v25 breaks tests with Web Storage API
• Node.js Releases: Current vs LTS policy (production guidance)
• Node.js Globals docs: Web Storage semantics + disable flag
• Node.js 25.0.0 release notes (V8 14.1, Web Storage default, performance highlights)
• Node.js 25.4.0 release notes (require(esm) stable, compile cache stable, ops improvements)
• Node.js node:module docs: module compile cache + portability
• Node.js Permissions docs: seat belt approach (not a sandbox)
• Node.js 25.5.0 release notes (--build-sea, other notable changes)
• Node.js Single Executable Applications docs (--build-sea flow and config)
• Node.js Deprecations docs: SlowBuffer removed + migration note
• twentyhq/twenty issue: crash on Node 25 due to SlowBuffer removal via dependency chain
• nodejs/Release issue #1113: cadence discussion (annual majors / LTS duration)
• nodejs/node issue: --build-sea fails in Windows Command Prompt (shell-specific behavior)
• Joyee Cheung: require(esm) in Node.js — from experiment to stability
• Joyee Cheung: Improving SEA building (why build moved into Node.js core)
Найкраща стратегія для більшості команд: прод на LTS, Node 25 у CI як ранній детектор регресій, і окремі експерименти для фіч 25.4/25.5 (require(esm), compile cache, build-sea). Так ти отримуєш DX-профіт без “дня, який зламав localStorage”.
Пов'язані статті
AI SEO / GEO у 2026: ваші наступні клієнти — не люди, а агенти
Пошук зміщується від кліків до відповідей. Боти та AI-агенти сканують, цитують, рекомендують і дедалі частіше купують. Дізнайтесь, що таке AI SEO / GEO, чому класичного SEO вже недостатньо, і як PAS7 Studio допомагає брендам перемагати у «агентному» вебі.
Найпотужніший чіп від Apple? M5 Pro і M5 Max б'ють рекорди
Аналітичний розбір Apple M5 Pro і M5 Max станом на березень 2026 року. Пояснюємо, чому ці чіпи можна вважати найпотужнішими професійними ноутбучними SoC від Apple, як вони виглядають на тлі M4 Pro, M4 Max, M1 Pro, M1 Max і що показують у порівнянні з актуальними Intel та AMD.
Artemis II і код, який веде до Місяця
У цьому блозі розбираємо місію NASA Artemis II, яка стартувала 1 квітня 2026 року, і пояснюємо, що вона насправді говорить про сучасну інженерію: бортове ПЗ, резервні контури, симуляції, телеметрію, людський контроль і дуже обережну роль ШІ в космічній сфері.
Автоматичне тегування та пошук збережених посилань
Інтеграція з GDrive/S3/Notion для автоматичного тегування та швидкого пошуку через пошукові API
Професійна розробка для вашого бізнесу
Створюємо сучасні веб-рішення та боти для бізнесу. Дізнайтеся, як ми можемо допомогти вам досягти цілей.