Один динамічний імпорт іконок вивів із ладу сервер розробки на машині з 16 ГБ оперативної пам'яті під керуванням Windows Subsystem for Linux 2 (WSL2), змусивши процес vmmemWSL поглинути всю доступну пам'ять і заморозити все вікно Linux. Збій стався під час запуску проєкту Next.js 16 з використанням Turbopack, і це сталося попри наявність файлу .wslconfig, який обмежує використання RAM віртуальною машиною.

Чому крихітний імпорт може стати монстром

Розробник намагався вирішувати питання з іконками під час виконання за допомогою динамічної точки входу. Імпорт підтягнув пакет іконок, що містить приблизно 9 000 модулів. Turbopack, бандлер на базі Rust, який забезпечує роботу сервера розробки Next.js 16, будує повну карту модулів для кожного пакета, до якого він звертається. У режимі розробки ця карта зберігається в пам'яті та оновлюється при кожній зміні файлу. Завантаження всього пакета іконок змусило Turbopack виділити величезний обсяг RAM, що швидко призвело до досягнення жорсткого ліміту, встановленого у файлі .wslconfig. Коли ліміт було досягнуто, віртуальна машина WSL перестала відповідати; Ctrl + C не допомагав, і єдиним виходом було примусове вимкнення хоста Windows.

Продуктивний білд (production build) того самого коду пройшов успішно, оскільки бандлер компілює граф один раз, створює активи та завершує роботу. Однак сервер розробки тримає граф у пам'яті для забезпечення гарячого перезавантаження (hot-reloading). Таким чином, успішний білд не гарантує, що середовище розробки зможе витримати таку ж схему імпорту.

Ширші наслідки

Розробники, які працюють із інструментами на базі Linux у Windows, покладаються на WSL2 для ізоляції використання ресурсів. Коли один імпорт вичерпує пам'ять віртуальної машини, весь хост може почати гальмувати або стати нечутливим, що впливає на будь-які інші контейнери чи застосунки на тій самій машині. Цей інцидент також підкреслює невідповідність між типовими прапорцями налаштування пам'яті Node.js та архітектурою Turbopack: Turbopack працює на Rust, а не на V8, тому збільшення прапорця Node --max-old-space-size ніяк не впливає на споживання RAM.

Що саме пішло не так

  • Динамічна точка входу: інструкція import просила бандлер розглядати весь пакет іконок як один модуль із лінивим завантаженням (lazy-loading). Turbopack відповів на це негайним (eager) парсингом кожного файлу для побудови карти модулів.
  • Граф сервера розробки: на відміну від разової продуктивної компіляції, сервер розробки зберігає повний граф залежностей у RAM, щоб забезпечити миттєвий зворотний зв'язок при зміні файлів.
  • Ліміт пам'яті: файл .wslconfig обмежував віртуальну машину лише частиною RAM хоста. Коли запит Turbopack перевищив цей ліміт, віртуальна машина зависла.

Виправлення, що зменшують споживання пам'яті вдвічі

Розробник застосував три практичні зміни, які зменшили використання RAM з 3,6 ГБ до 1,87 ГБ і відновили стабільність:

  1. Припиніть використовувати динамічні точки входу для дрібних активів – імпортуйте лише ті іконки, які вам потрібні, наприклад: import { SearchIcon } from 'icon-pack/search'. Якщо вам потрібна лише невелика кількість, вбудовані (inline) SVG будуть ще легшими.
  2. Увімкніть optimizePackageImports у next.config.ts – ця опція вказує Turbopack розв'язувати імпорти до конкретних шляхів файлів замість кореня пакета, що запобігає завантаженню всього дерева пакетів.
  3. Не покладайтеся на прапорці купи (heap flags) Node – оскільки використання пам'яті Turbopack регулюється його середовищем виконання Rust, --max-old-space-size не впливає на вирішення проблеми.

Рекомендується залишати обмеження у .wslconfig. Жорсткий ліміт може змусити віртуальну машину поставити процеси на паузу, а не призвести до збою хоста Windows, що дасть вам шанс втрутитися до того, як усе зупиниться.

На що звернути увагу у своєму робочому процесі

  • Дашборди пам'яті: такі інструменти, як htop у WSL або Диспетчер завдань Windows, можуть показати, коли споживання vmmemWSL різко зростає. Налаштуйте сповіщення, якщо використання наближається до встановленого ліміту.
  • Аудит розміру пакетів: перед додаванням бібліотеки перевірте, скільки модулів вона містить. Великі набори іконок, колекції утиліт або бібліотеки компонентів можуть непомітно роздувати граф розробки.
  • Вибірковий імпорт: віддавайте перевагу іменованим імпортам або прямим шляхам до файлів замість використання символів підстановки (wildcards) або динамічних імпортів, особливо в середовищі розробки, де бандлер тримає все в пам'яті.
  • Паритет продуктивного та середовища розробки: розглядайте успішний продуктивний білд як окремий етап перевірки. Запускайте сервер розробки з монітором пам'яті, щоб виявити проблеми, які з'являються лише під час гарячого перезавантаження.

Висновок

Один динамічно імпортований пакет іконок може спожити стільки RAM, що це паралізує сервер розробки Next.js на базі WSL2, навіть якщо ресурси хоста навмисно обмежені. Уникаючи широких динамічних імпортів, вмикаючи оптимізацію імпортів на рівні пакетів та контролюючи використання пам'яті, розробники можуть підтримувати швидкість роботи своїх середовищ Linux у Windows та уникати примусового вимкнення системи.