Avatar ·

Как передать аргументы командной строки в npm-скрипт?

Всем привет! Я новичок в Node.js и npm. У меня есть package.json с несколькими скриптами. Например, я хочу запустить тесты с разными параметрами: иногда с флагом --watch, иногда с указанием конкретного файла. Сейчас я делаю так: ```json { "scripts": { "test": "mocha", "test:watch": "mocha --watch", "test:file": "mocha test/somefile.js" } } ``` Но это ужасно неудобно — приходится создавать отдельный скрипт для каждого варианта. Я хочу иметь один скрипт `test`, но передавать ему аргументы прямо из командной строки, например: ``` npm run test -- --watch npm run test -- --grep "pattern" npm run test test/mytest.js ``` Но почему-то это не работает — аргументы не доходят до mocha. Я пробовал разные варианты: с двойным дефисом, без него, с кавычками — ничего не помогает. Может быть, есть специальный синтаксис? Или нужно использовать какие-то переменные окружения? Подскажите, пожалуйста, как правильно передавать аргументы в npm-скрипты. Заранее спасибо! <<>>

Проблема передачи аргументов в npm-скрипты

Вы столкнулись с типичной проблемой: npm по умолчанию не передаёт аргументы, указанные после имени скрипта, напрямую в исполняемую команду. Однако есть несколько проверенных способов решить эту задачу.

Решение 1: Использование двойного дефиса (--)

Самый простой и официальный способ — передавать аргументы после --. Все, что идёт после двойного дефиса, будет передано в ваш скрипт как аргументы командной строки.

npm run test -- --watch

В вашем package.json скрипт должен быть таким:

{
  "scripts": {
    "test": "mocha"
  }
}

Теперь npm run test -- --watch выполнит mocha --watch. Обратите внимание: двойной дефис обязателен — он отделяет аргументы npm от аргументов вашего скрипта.

Решение 2: Использование переменной окружения npm_config_

Если вам нужно передавать сложные аргументы или вы хотите больше контроля, используйте переменные окружения. npm автоматически создаёт переменные npm_config_* для аргументов, переданных через --.

// package.json
{
  "scripts": {
    "test": "node testrunner.js"
  }
}

// testrunner.js
const watchMode = process.env.npm_config_watch === 'true';
const grepPattern = process.env.npm_config_grep;

if (watchMode) {
  console.log('Running in watch mode');
}
if (grepPattern) {
  console.log(`Filtering by pattern: ${grepPattern}`);
}

Запуск:

npm run test -- --watch=true --grep="my test"

Решение 3: Использование пакета cross-env (для кросс-платформенности)

Если вы работаете в Windows и используете переменные окружения, cross-env поможет избежать проблем с синтаксисом:

npm install --save-dev cross-env

// package.json
{
  "scripts": {
    "test": "cross-env-shell mocha $npm_config_watch"
  }
}

Запуск:

npm run test -- --watch=--watch

Решение 4: Передача аргументов через переменные среды (продвинутый способ)

Вы можете определить свои переменные прямо в команде запуска:

{
  "scripts": {
    "test": "mocha"
  }
}

// Запуск с переменной
MOCHA_OPTIONS="--watch --grep pattern" npm run test

Затем в коде или конфигурации mocha вы можете читать process.env.MOCHA_OPTIONS.

Важные замечания

  • Двойной дефис — это стандартный способ, поддерживаемый всеми версиями npm.
  • Аргументы, переданные через --, не попадают в process.argv самого скрипта, если вы не используете специальные утилиты (например, yargs или commander).
  • Для простых случаев (как с mocha) достаточно двойного дефиса — mocha сам обработает аргументы.
  • Если ваш скрипт написан на JavaScript и использует process.argv, убедитесь, что вы парсите аргументы правильно (первые два элемента — это node и путь к скрипту).

Пример для вашего случая с mocha

Просто оставьте в package.json:

{
  "scripts": {
    "test": "mocha"
  }
}

И вызывайте:

npm run test -- --watch
npm run test -- --grep "my test"
npm run test -- test/mytest.js

Всё будет работать как часы!

<<>>

Альтернативный подход: Использование npm-пакетов для управления аргументами

Если вы часто передаёте сложные аргументы и хотите больше гибкости, рассмотрите специализированные пакеты:

1. npm-run-all

Позволяет запускать несколько скриптов последовательно или параллельно с передачей аргументов:

npm install --save-dev npm-run-all

// package.json
{
  "scripts": {
    "test": "run-s test:lint test:unit",
    "test:lint": "eslint .",
    "test:unit": "mocha"
  }
}

Запуск с аргументами:

npm run test -- -- --watch

2. concurrently

Для параллельного запуска нескольких скриптов с общими аргументами:

npm install --save-dev concurrently

{
  "scripts": {
    "dev": "concurrently \"npm run server\" \"npm run client\"",
    "server": "node server.js",
    "client": "webpack-dev-server"
  }
}

Передача аргументов:

npm run dev -- --port=3000

3. Использование .env файлов

Для сложных конфигураций создайте .env файл и используйте пакет dotenv:

npm install dotenv

// .env
WATCH=true
GREP_PATTERN=my-test

// package.json
{
  "scripts": {
    "test": "node -r dotenv/config testrunner.js"
  }
}

Этот подход удобен, когда у вас много параметров и вы хотите хранить их отдельно от командной строки.

Совет: Для простых случаев используйте двойной дефис. Для сложных проектов — комбинируйте переменные окружения и специализированные пакеты. Главное — не усложняйте там, где можно обойтись простым решением.