Programming

Node.js-тулинг

Инструменты вокруг Node.js — nvm для переключения версий, npm/yarn/pnpm для зависимостей, сборщики, линтеры и менеджеры процессов.

Что такое Node.js-тулинг

Сам Node.js — только среда выполнения JavaScript. Всё остальное, из чего складывается рабочий проект, живёт вокруг: выбор версии Node, установка зависимостей, сборка, линтинг, запуск в проде. Ниже — что из этого что.

nvm — что это

nvm (Node Version Manager) — утилита для установки нескольких версий Node.js на одной машине и мгновенного переключения между ними.

Зачем: старый проект работает на Node 18, новый требует Node 22, а на сервере стоит третья версия. Глобально установленная Node одна, и без nvm переключение означает переустановку.

nvm install 22          # поставить конкретную версию
nvm install --lts       # последнюю LTS
nvm use 18              # переключиться в текущей сессии терминала
nvm alias default 22    # версия по умолчанию для новых сессий
nvm ls                  # что установлено

Ключевая деталь: nvm use действует только в текущем окне терминала. В новом всё вернётся к default — это регулярно сбивает с толку.

Проект фиксирует свою версию файлом .nvmrc в корне репозитория:

echo "22" > .nvmrc
nvm use          # прочитает .nvmrc и переключится

Технически nvm — это shell-функция, а не бинарник: она правит PATH текущей оболочки, потому и работает только в ней. Отсюда же следствие: под Windows настоящий nvm не работает — там ставят отдельный проект nvm-windows с похожими командами. Более быстрые альтернативы — fnm и Volta, они кроссплатформенные.

Менеджеры пакетов

npm yarn pnpm
Идёт с Node Да Нет Нет
Место на диске Копия пакетов в каждом проекте Копия Общий store и жёсткие ссылки
Скорость установки Базовая Выше Обычно самая высокая
Строгость зависимостей Плоское дерево Плоское Строгое: нельзя импортировать то, чего нет в package.json
Lock-файл package-lock.json yarn.lock pnpm-lock.yaml

Главный практический аргумент за pnpm — диск и время: он не копирует один и тот же пакет в двадцать проектов, а хранит один экземпляр в общем store. На CI-раннере и в Docker-сборке это экономит минуты.

package.json и lock-файл

package.json описывает проект и диапазоны версий, lock-файл фиксирует точные версии всего дерева, включая транзитивные зависимости.

{
  "scripts": { "dev": "vite", "build": "vite build", "test": "vitest run" },
  "dependencies": { "express": "^4.19.2" },
  "devDependencies": { "vitest": "^2.0.0" }
}

^4.19.2 разрешает 4.20.0, но не 5.0.0. Без lock-файла двое разработчиков получат разные версии — это и есть «у меня работает».

Отсюда правило для CI/CD: в пайплайне и в Docker-образе ставьте зависимости через npm ci, а не npm install. ci ставит ровно то, что в lock-файле, падает при расхождении с package.json и не переписывает lock. install может тихо обновить версии — сборка перестанет быть воспроизводимой.

Разделение dependencies / devDependencies тоже практично: в продовом образе ставится npm ci --omit=dev, и образ худеет.

Сборщики и линтеры

  • Vite — стандарт для фронтенда: мгновенный дев-сервер, сборка через Rollup.
  • esbuild / SWC — сборщики на Go и Rust, на порядок быстрее webpack; часто работают внутри других инструментов.
  • webpack — исторический стандарт, гибкий и медленный; всё ещё много где живёт.
  • TypeScript — статическая типизация поверх JS, ловит ошибки до запуска.
  • ESLint — поиск проблем в коде, Prettier — форматирование. Первый про смысл, второй про запятые; ставят обычно оба и вешают на pre-commit.

Запуск в проде

Node-процесс однопоточный: он использует одно ядро, а при необработанном исключении просто умирает. Значит, нужен супервизор.

pm2 start app.js -i max     # по процессу на ядро, автоперезапуск
pm2 startup && pm2 save     # подняться после ребута

-i max поднимает кластер по числу ядер CPU — иначе на VPS с 4 ядрами будет работать одно. Альтернатива pm2 без лишних зависимостей — юнит systemd с Restart=always; в Kubernetes перезапуском занимается сам оркестратор, и pm2 там лишний.

Отдельная боль — node_modules: сотни мегабайт и десятки тысяч файлов. В Docker-образе это лечится многоступенчатой сборкой (собрали в одном слое, в финальный положили только результат и продовые зависимости) и .dockerignore, куда node_modules кладут первой строкой.

Связанные термины

  • Node.js — среда, вокруг которой всё это построено
  • Docker — где важны npm ci и многоступенчатая сборка
  • CI/CD — основной потребитель lock-файлов
  • VPS — типичное место запуска Node-приложения
  • systemd — альтернатива pm2 для автозапуска
  • IDE — где ESLint и TypeScript подсвечивают ошибки на лету

Готовы запустить GPU-задачу?

Запустить GPU-сервер