Один динамический импорт иконок вывел из строя dev-сервер на машине с 16 ГБ оперативной памяти под управлением Windows Subsystem for Linux 2 (WSL2), заставив процесс vmmemWSL поглотить всю доступную память и заморозить всё окно Linux. Сбой произошел во время работы проекта Next.js 16 с использованием Turbopack, причем это случилось, несмотря на наличие файла .wslconfig, ограничивающего использование RAM виртуальной машиной.
Почему крошечный импорт может стать монстром
Разработчик пытался разрешать иконки во время выполнения с помощью динамической точки входа. Импорт подтянул пакет иконок, содержащий примерно 9 000 модулей. Turbopack — бандлер на базе Rust, на котором работает dev-сервер Next.js 16, — строит полную карту модулей для каждого пакета, с которым он взаимодействует. В режиме разработки эта карта хранится в памяти и обновляется при каждом изменении файла. Загрузка всего пакета иконок заставила Turbopack выделить огромное количество RAM, что быстро привело к достижению жесткого лимита, установленного в файле .wslconfig. Как только лимит был достигнут, виртуальная машина WSL перестала отвечать; Ctrl + C не помогал, и единственным выходом было принудительное завершение работы хоста Windows.
Production-сборка того же кода прошла успешно, потому что бандлер компилирует граф один раз, выпускает ассеты и завершает работу. Однако dev-сервер держит граф в памяти для обеспечения hot-reloading. Таким образом, успешная сборка (green build) не гарантирует, что среда разработки сможет пережить тот же паттерн импорта.
Более широкие последствия
Разработчики, использующие Linux-инструментарий внутри Windows, полагаются на WSL2 для изоляции использования ресурсов. Когда один единственный импорт исчерпывает память виртуальной машины, весь хост может стать медленным или перестать реагировать на команды, что затронет любые другие контейнеры или приложения на той же машине. Инцидент также подчеркивает несоответствие между типичными флагами настройки памяти Node.js и архитектурой Turbopack: Turbopack работает на Rust, а не на V8, поэтому увеличение флага Node --max-old-space-size никак не помогает ограничить его потребление RAM.
Что именно пошло не так
- Динамическая точка входа: инструкция
importпросила бандлер рассматривать весь пакет иконок как единый модуль с ленивой загрузкой. Turbopack ответил немедленным (eager) парсингом каждого файла для построения карты модулей. - Граф dev-сервера: в отличие от разовой production-компиляции, dev-сервер удерживает полный граф зависимостей в RAM, чтобы мгновенно реагировать на изменения файлов.
- Лимит памяти: файл .wslconfig ограничивал виртуальную машину лишь частью оперативной памяти хоста. Когда запросы Turbopack превысили этот лимит, виртуальная машина зависла.
Решения, сократившие потребление памяти вдвое
Разработчик применил три практических изменения, которые снизили потребление RAM с 3,6 ГБ до 1,87 ГБ и восстановили стабильность:
- Откажитесь от использования динамических точек входа для мелких ассетов — импортируйте только те иконки, которые вам нужны, например:
import { SearchIcon } from 'icon-pack/search'. Если вам нужно всего несколько штук, инлайновые SVG будут еще легче. - Включите
optimizePackageImportsвnext.config.ts— эта опция указывает Turbopack разрешать импорты до конкретных путей к файлам, а не до корня пакета, предотвращая загрузку всего дерева пакета. - Не полагайтесь на флаги кучи (heap) Node — поскольку потребление памяти Turbopack регулируется его средой выполнения на Rust, флаг
--max-old-space-sizeне влияет на проблему.
Соблюдение лимитов в .wslconfig по-прежнему рекомендуется. Жесткое ограничение может привести к тому, что виртуальная машина просто приостановит работу, а не обрушит хост Windows, что даст вам шанс вмешаться до того, как всё окончательно зависнет.
На что стоит обратить внимание в своем рабочем процессе
- Панели мониторинга памяти: такие инструменты, как
htopвнутри WSL или Диспетчер задач Windows, могут показать моменты скачков vmmemWSL. Настройте оповещения, если использование памяти приближается к вашему установленному лимиту. - Аудит размера пакетов: прежде чем добавлять библиотеку, проверьте, сколько модулей она содержит. Большие наборы иконок, коллекции утилит или библиотеки компонентов могут незаметно раздуть граф разработки.
- Выборочные импорты: отдавайте предпочтение именованным импортам или прямым путям к файлам вместо wildcard-импортов или динамических импортов, особенно в среде разработки, где бандлер держит всё в памяти.
- Паритет между production и dev: рассматривайте успешную production-сборку как отдельный этап проверки. Запускайте dev-сервер с монитором памяти, чтобы отловить проблемы, которые проявляются только во время hot-reloading.
Вывод
Один динамически импортированный пакет иконок может поглотить достаточно RAM, чтобы парализовать dev-сервер Next.js на базе WSL2, даже если ресурсы хоста намеренно ограничены. Избегая широких динамических импортов, включая оптимизацию импортов на уровне пакетов и отслеживая использование памяти, разработчики могут поддерживать отзывчивость своих сред Linux внутри Windows и избегать принудительных перезагрузок системы.
