Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Несколько версий Node на ноутбуке: nvm, fnm и Volta

Менеджеры версий Node: nvm, fnm или Volta — как жить с несколькими проектами

Зачем разработчику несколько версий Node.js и как их держать: сравнение nvm, fnm и Volta, фиксация версии в проекте, engines и .nvmrc, скорость переключения и грабли Windows.

Прямой ответ

Node-проекты живут на разных мажорных версиях: легаси-приложение на 16, текущий прод на 20 LTS, эксперименты на 22 — и всё это одновременно на одном ноутбуке. Системная установка Node такое не поддерживает, поэтому стандартом стали менеджеры версий: nvm (классика, bash-скрипт), fnm (Rust-перепис nvm, в разы быстрее, кросс-платформенный включая нативный Windows) и Volta (фиксирует версию на проект автоматически, по package.json). Рекомендация 2026: на macOS/Linux — fnm (скорость) или nvm (привычка и совместимость со всем туториалами); на Windows — fnm или Volta (nvm-windows — отдельный проект с другим поведением); для команд, которым важна воспроизводимость «у всех одинаково», — Volta.

Почему версий несколько: механика проблемы

Мажорные версии Node ломают обратную совместимость (обновлённый V8, изменения в API, требование новых инструментов сборки); нативные зависимости (модули с C-кодом) компилируются под конкретную версию и при её смене требуют пересборки. Симптом жизни без менеджера: «обновил Node — половина глобальных пакетов сломалась, а старый проект перестал собираться». Менеджер версий изолирует установки друг от друга: каждая версия живёт в своём каталоге со своим npm и глобальными пакетами; переключение меняет PATH. Аналогия для Python-разработчиков: это nvm-эквивалент связки pyenv/venv из статьи про Python-окружения.

nvm: стандарт, с которого начинают

nvm install 20        # поставить LTS
nvm install 22
nvm use 20            # переключить в текущей оболочке
nvm alias default 20  # версия по умолчанию

Плюсы: нулевая конфигурация проекта, знаком всем, работает везде на Unix. Минусы: медленный старт оболочки (bash-скрипт инициализируется сотни миллисекунд — заметно при частом открытии терминалов), на Windows — только форк nvm-windows с отличающимися командами, автопереключения по проекту нет (вручную nvm use).

fnm: тот же UX, быстрые внутренности

fnm install 20 && fnm use 20
# автопереключение по .nvmrc/.node-version при входе в каталог:
eval "$(fnm env --use-on-cd)"

Команды почти копируют nvm (миграция безболезненна), но fnm написан на Rust: установка и переключение мгновенные, shell-init не тормозит терминал, один бинарник честно работает на Windows/macOS/Linux. Фича, которая меняет привычки: --use-on-cd — при cd в проект с .nvmrc версия переключается сама; ошибка «собрал не той версией» исчезает.

Volta: версия как свойство проекта

Volta идёт дальше: она пиннит инструмент в package.json:

volta pin node@20    # запишет "volta": {"node": "20.x"} в package.json

После этого любой запуск node/npm в каталоге проекта автоматически исполняется на закрепённой версии — без use, без .nvmrc, у каждого члена команды одинаково. Дополнительно Volta фиксирует и версии глобальных CLI-пакетов (volta install typescript — доступён во всех проектах на нужной версии). Цена: свой подход к глобальным пакетам (не совместим с «просто npm -g») и чуть меньше экосистемной привычности.

Практика команды: фиксация и engines

Независимо от менеджера, проект обязан декларировать версию:

  1. .nvmrc/.node-version с мажорной версией — читают nvm/fnm.
  2. engines в package.json: {"node": ">=20 <21"} — npm предупредит при несоответствии (жёсткость — через engine-strict=true в .npmrc).
  3. CI на той же мажорной версии, что прод: расхождение «CI на 22, прод на 20» — источник сюрпризов после релиза.

Типовые грабли: глобальные пакеты ставятся под конкретную версию (nvm use 22 && npm i -g pnpm — pnpm появится только в 22); после nvm install новой версии глобальный набор пуст — переустановите или перенесите (nvm reinstall-packages 20). Диск: каждая версия Node — 100–150 МБ плюс свои кэши; пять версий — уже полгигабайта, аудит вместе с node_modules — в статье про место на диске.

Что выбрать: коротко

Одиночный разработчик на macOS/Linux, несколько проектов — fnm (скорость + автопереключение). Команда с требованием идентичности окружений — Volta (пиннинг в package.json). «Как в туториале» и минимум нового — nvm. Windows без WSL — fnm или Volta (оба нативные). Во всех случаях системный Node из установщика лучше удалить, чтобы PATH не двоился — частая причина «nvm use не работает».

И финальный аргумент дисциплины: менеджер версий делает видимой саму проблему версий. Когда проект декларирует Node в файле, а оболочка переключается автоматически, расхождение «собрал не тем Node» перестаёт быть плавающим багом — оно либо исключено, либо диагностируется одной командой. Это редкий случай, когда инструмент окупается не скоростью, а исчезновением класса ошибок.

FAQ

Менеджер версий замедлит сборку? Нет: после переключения вы работаете с обычным Node; накладные расходы есть только у nvm на инициализацию оболочки, fnm/Volta почти мгновенны.

Можно ли держать Node и через brew/apt, и через менеджер? Технически да, практически — источник путаницы с PATH и правами на глобальные пакеты. Выберите один источник; менеджер версий покрывает все сценарии.

Как обновлять LTS-версии? fnm install 20 (или nvm) подтянет свежий минор 20.x; минорные обновления обратно совместимы в пределах мажорной линии — обновляйте регулярно, это патчи безопасности.

Нужен ли менеджер версий, если проект один? Пока один — можно и без него, но установка занимает две минуты и избавляет от будущей ручной миграции; дешевле завести сразу.

Частные случаи, которые всплывают в работе

Нативные модули при переключении версий: пакеты с C-кодом (bcrypt-подобные, sharp) компилируются под конкретную версию Node ABI; после nvm use 22 они требуют пересборки (npm rebuild). Симптом — ошибки NODE_MODULE_VERSION mismatch; лечение — rebuild или переустановка node_modules.

Docker и версии: в контейнере версия Node задаётся базовым образом (node:20-alpine) и не зависит от менеджера на хосте — это правильно: прод-версия фиксируется в Dockerfile, локальная — в .nvmrc, и они должны совпадать мажорно. Расхождение «локально 22, в образе 18» — источник «у меня работает».

Глобальные CLI и PATH: у каждой версии свой набор глобальных пакетов; если tsc «исчез» после переключения — он стоял под другой версией. Решение — ставить такие инструменты через менеджер, который их шарит (Volta), или через pnpm/npx вместо npm -g.

Обновление LTS в команде: договоритесь о ритме (новый LTS — в течение месяца после стабилизации), зафиксируйте его в CI-матрице — и расхождение версий перестанет быть темой для споров.

Как менеджер версий уживается с Docker? Они не пересекаются: в контейнере версия Node определяется базовым образом, на хосте — менеджером. Важно лишь совпадение мажорных версий локальной и контейнерной — иначе «локально собирается, в образе нет». Фиксируйте обе: .nvmrc для хоста, точный тег в Dockerfile.

Что выбрать для команды с разными ОС? Volta или fnm: оба кросс-платформенные и читают один файл версии проекта. nvm плюс nvm-windows — две разные программы с разным поведением, в смешанных командах это постоянный источник мелких расхождений.

Как быстро проверить, какой Node сейчас активен и откуда он? Команды which node (Linux/macOS) или Get-Command node (PowerShell) показывают путь исполняемого файла: если он ведёт в каталог менеджера — всё правильно; если в системные каталоги — PATH конфликтует с менеджером версий.

Источники: проекты nvm, fnm, документация Volta (ссылки в шапке).