web-dev-qa-db-fra.com

Envoi des arguments de ligne de commande au script npm

La partie scripts de mon package.json ressemble actuellement à ceci:

"scripts": {
    "start": "node ./script.js server"
}

... ce qui signifie que je peux exécuter npm start pour démarrer le serveur. Jusqu'ici tout va bien.

Cependant, j'aimerais pouvoir exécuter quelque chose comme npm start 8080 et faire passer le ou les arguments à script.js (par exemple npm start 8080 => node ./script.js server 8080). Est-ce possible?

507
arnemart

Edit 2014.10.30:Il est possible de transmettre des arguments à npm run à partir de npm 2.0.0

La syntaxe est la suivante:

npm run <command> [-- <args>]

Notez le -- nécessaire. Il est nécessaire de séparer les paramètres transmis à la commande npm et les paramètres transmis à votre script.

Donc, si vous avez dans package.json

"scripts": {
    "grunt": "grunt",
    "server": "node server.js"
}

Alors les commandes suivantes seraient équivalentes:

grunt task:target => npm run grunt -- task:target

node server.js --port=1337 => npm run server -- --port=1337

Pour obtenir la valeur du paramètre, voir cette question . Pour lire les paramètres nommés, il est probablement préférable d'utiliser une bibliothèque d'analyse telle que yargs ou minimist ; nodejs expose process.argv globalement, contenant les valeurs des paramètres de ligne de commande, mais il s'agit d'une API de bas niveau (tableau de chaînes séparées par des espaces, fournies par le système d'exploitation à l'exécutable du noeud). 


Edit 2013.10.03: Ce n'est actuellement pas possible directement. Mais il y a un problème connexe GitHub ouvert le npm pour mettre en œuvre le comportement que vous demandez. Il semble que le consensus soit de le mettre en œuvre, mais cela dépend d'un autre problème qui doit être résolu auparavant.


Réponse originale: Comme solution de contournement (bien que peu pratique), vous pouvez procéder comme suit:

Dites que le nom de votre paquet à partir de package.json est myPackage et que vous avez également

"scripts": {
    "start": "node ./script.js server"
}

Ajoutez ensuite package.json:

"config": {
    "myPort": "8080"
}

Et dans votre script.js:

// defaulting to 8080 in case if script invoked not via "npm run-script" but directly
var port = process.env.npm_package_config_myPort || 8080

Ainsi, par défaut, npm start utilisera 8080. Vous pouvez toutefois le configurer (la valeur sera stockée par npm dans sa mémoire interne):

npm config set myPackage:myPort 9090

Ensuite, lors de l'appel de npm start, 9090 sera utilisé (la valeur par défaut de package.json est remplacée).

736
jakub.g

Vous avez demandé à pouvoir exécuter quelque chose commenpm start 8080. Ceci est possible sans avoir besoin de modifier script.js ou les fichiers de configuration comme suit.

Par exemple, dans votre valeur JSON "scripts", include--

"start": "node ./script.js server $PORT"

Et ensuite à partir de la ligne de commande:

$ PORT=8080 npm start

J'ai confirmé que cela fonctionne avec bash et npm 1.4.23. Notez que cette solution ne nécessite pas la résolution de GitHub npm issue # 3494 .

164
cjerdonek

Vous pouvez aussi faire ça:

Dans package.json:

"scripts": {
    "cool": "./cool.js"
}

Dans cool.js:

 console.log({ myVar: process.env.npm_config_myVar });

En CLI:

npm --myVar=something run-script cool

Devrait-il produire:

{ myVar: 'something' }

Mise à jour: avec npm 3.10.3, il apparaît que les variables process.env.npm_config_ sont minuscules? J'utilise aussi better-npm-run, alors je ne suis pas sûr qu'il s'agisse d'un comportement par défaut de Vanilla ou non, mais cette réponse est fonctionne. Au lieu de process.env.npm_config_myVar, essayez process.env.npm_config_myvar

78
francoisrv

La réponse de jakub.g est correcte, mais un exemple utilisant grunt semble un peu complexe.

Donc ma réponse plus simple:

- Envoi d'un argument de ligne de commande à un script npm

Syntaxe d'envoi des arguments de ligne de commande à un script npm:

npm run [command] [-- <args>]

Imaginez que nous ayons une tâche de démarrage npm dans notre package.json pour lancer le serveur de développement webpack:

"scripts": {
  "start": "webpack-dev-server --port 5000"
},

Nous exécutons ceci à partir de la ligne de commande avec npm start 

Maintenant, si nous voulons passer un port au script npm:

"scripts": {
  "start": "webpack-dev-server --port process.env.port || 8080"
},

exécuter ceci et passer le port, par exemple 5000 via la ligne de commande serait comme suit:

npm start --port:5000

- Utilisation de package.json config:

Comme mentionné par jakub.g, vous pouvez également définir des paramètres dans la configuration de votre package.json

"config": {
  "myPort": "5000"
}

"scripts": {
  "start": "webpack-dev-server --port process.env.npm_package_config_myPort || 8080"
},

npm start utilisera le port spécifié dans votre configuration, ou bien vous pourrez le remplacer

npm config set myPackage:myPort 3000

- Définir un paramètre dans votre script npm

Un exemple de lecture d'une variable définie dans votre script npm. Dans cet exemple NODE_ENV

"scripts": {
  "start:prod": "NODE_ENV=prod node server.js",
  "start:dev": "NODE_ENV=dev node server.js"
},

lisez NODE_ENV dans server.js soit prod ou dev

var env = process.env.NODE_ENV || 'prod'

if(env === 'dev'){
    var app = require("./serverDev.js");
} else {
    var app = require("./serverProd.js");
}
57
steven iseki

Utilisez process.argv dans votre code, puis fournissez simplement un $* final à votre entrée de valeur de script.

Par exemple, essayez-le avec un script simple qui enregistre simplement les arguments fournis dans la sortie standard echoargs.js:

console.log('arguments: ' + process.argv.slice(2));

package.json:

"scripts": {
    "start": "node echoargs.js $*"
}

Exemples:

> npm start 1 2 3
arguments: 1,2,3

process.argv[0] est l'exécutable (noeud), process.argv[1] est votre script.

Testé avec npm v5.3.0 et noeud v8.4.0

23
Peter

Si vous souhaitez passer des arguments au milieu d'un script npm, au lieu de simplement les ajouter à la fin, les variables d'environnement inline semblent bien fonctionner:

"scripts": {
  "dev": "BABEL_ARGS=-w npm run build && cd lib/server && nodemon index.js",
  "start": "npm run build && node lib/server/index.js",
  "build": "mkdir -p lib && babel $BABEL_ARGS -s inline --stage 0 src -d lib",
},

Ici, npm run dev passe l'indicateur de surveillance -w à babel, mais npm run start exécute une fois une construction normale.

13
Dan Ross

Cela ne répond pas vraiment à votre question mais vous pouvez toujours utiliser des variables d'environnement à la place:

"scripts": {
    "start": "PORT=3000 node server.js"
}

Puis dans votre fichier server.js:

var port = process.env.PORT || 3000;
5
DrunkenBeetle

D'après ce que je vois, les gens utilisent les scripts package.json lorsqu'ils souhaitent exécuter le script de manière plus simple. Par exemple, pour utiliser nodemon installé dans les nœuds_modules locaux, nous ne pouvons pas appeler nodemon directement à partir du cli, mais nous pouvons l'appeler à l'aide de ./node_modules/nodemon/nodemon.js. Donc, pour simplifier cette longue frappe, nous pouvons mettre ceci ...


 ...

 scripts: {
 'start': 'nodemon app.js' 
 } 

 ...

... puis appelez npm start pour utiliser 'nodemon' qui a app.js comme premier argument.

Ce que j'essaie de dire, si vous voulez juste démarrer votre serveur avec la commande node, je ne pense pas que vous ayez besoin d'utiliser scripts. Taper npm start ou node app.js nécessite le même effort.

Mais si vous voulez utiliser nodemon et que vous souhaitez passer un argument dynamique, n'utilisez pas non plus script. Essayez d'utiliser symlink à la place.

Par exemple, utiliser la migration avec sequelize. Je crée un lien symbolique ...

ln -s node_modules/sequelize/bin/sequelize sequelize

... Et je peux passer n'importe quel argument quand je l'appelle ...

./sequlize -h /* show help */

./sequelize -m /* upgrade migration */

./sequelize -m -u /* downgrade migration */

etc...

À ce stade, utiliser un lien symbolique est la meilleure façon de comprendre, mais je ne pense pas vraiment que ce soit la meilleure pratique.

J'espère aussi votre avis à ma réponse.

3
Kiddo

npm run script_target - <argument> Fondamentalement, c’est la façon de passer les arguments de la ligne de commande, mais cela ne fonctionne que dans le cas où le script ne dispose que d’une seule commande, comme j’exécute une commande, à savoir npm run start - 4200

"script":{
       "start" : "ng serve --port="
 }

Cela fonctionnera pour passer des paramètres de ligne de commande, mais que faire si nous lançons plus d’une commande en même temps, comme npm, exécutez build c:/workspace/file 

"script":{
       "build" : "copy c:/file <arg> && ng build"
 } 

mais il interprètera comme ceci lors de l'exécution de copie c:/fichier && ng construire c:/espace de travail/fichier et nous attendons quelque chose comme ceci copie c:/fichier c:/espace de travail/fichier && ng build

Remarque: - Le paramètre de ligne de commande so ne fonctionne que dans les cas où il n'y a qu'une seule commande dans un script.

J'ai lu quelques réponses ci-dessus dans lesquelles certaines d'entre elles écrivent qu'il est possible d'accéder au paramètre de ligne de commande à l'aide de $ symbol mais que cela ne fonctionnera pas 

0
Sunny Goel

J'ai utilisé la méthode suivante pour effectuer un test

  "scripts": {  
       "test-one": "mocha --timeout 90000 --watch --require ts-node/register --watch-extensions ts $1"
}

Pour exécuter le test utilisé commande suivante

npm run test-one ./e2e/<test_file_path>

Je n'ai pas besoin d'utiliser de configuration pour cela. Je pense que vous pouvez faire passer un argument de la même façon que je le fais ici.

0
Kamrul

J'ai trouvé cette question alors que j'essayais de résoudre mon problème en exécutant la commande sequelize seed: generate cli:

node_modules/.bin/sequelize seed:generate --name=user

Laissez-moi aller au but. Je voulais avoir une courte commande de script dans mon package.json fichier et fournir en même temps l'argument --name

La réponse est venue après quelques expériences. Voici ma commande dans package.json

"scripts: {
  "seed:generate":"NODE_ENV=development node_modules/.bin/sequelize seed:generate"
}

... et voici un exemple de son exécution dans un terminal pour générer un fichier de démarrage pour un utilisateur

> yarn seed:generate --name=user

> npm run seed:generate -- --name=user

FYI

yarn -v
1.6.0

npm -v
5.6.0
0
Serge Seletskyy