npmスクリプトへのコマンドライン引数の送信


819

scripts私のpackage.json現在の部分は次のようになります:

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

...つまりnpm start、実行してサーバーを起動できます。ここまでは順調ですね。

しかし、私はのようなものを実行しnpm start 8080、引数を渡せるようにしたいと思いますscript.js(例:npm start 8080=> node ./script.js server 8080)。これは可能ですか?

回答:


1132

2014.10.30を編集: npm 2.0.0以降、argsを渡すことが可能npm run

構文は次のとおりです。

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

必要なことに注意してください--npmコマンド自体に渡されるパラメーターとスクリプトに渡されるパラメーターを分離する必要があります。

だからあなたが持っている場合 package.json

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

その場合、次のコマンドは同等になります。

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

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

パラメータ値を取得するには、この質問を参照してください。名前付きパラメータを読み取るには、おそらくyargsminimistなどの解析ライブラリを使用するのが最善です。nodejsはprocess.argvコマンドラインパラメータ値を含むグローバルに公開しますが、これは低レベルAPI(オペレーティングシステムがノード実行可能ファイルに提供する、空白で区切られた文字列の配列)です。


2013.10.03を編集:現在のところ、直接行うことはできません。しかし、あなたが求めている振る舞いを実装するために開かれnpmた、関連するGitHubの問題があります。コンセンサスはこれを実装することですが、それは以前に解決されている別の問題に依存します。


元の回答:ある種の回避策として(あまり便利ではありません)、次のように実行できます。

からのパッケージ名を言うpackage.jsonmyPackage、あなたも持っています

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

次に追加package.json

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

そしてあなたの中で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

その方法では、デフォルトでnpm start8080を使用します。ただし、構成することはできます(値はnpm内部ストレージに格納されます)。

npm config set myPackage:myPort 9090

次に、を呼び出すとnpm start、9090が使用されます(デフォルトのpackage.jsonはオーバーライドされます)。


1
これものようなパッケージと完全に連動しますyargs。の後のすべてのパラメータ--は、スクリプトで完全に解析できます。
トーマス

11
AFAIKS、これはスクリプトの最後にパラメーターを追加することを可能にするだけです。途中でパラメーターが必要な場合はどうしますか?
Spock

109
-- --args奇妙ですが大丈夫です
2017

9
@Spockシェル関数を使用できます。これは、 "npm run lint--f unix": "lint": "f(){eslint -f codeframe $ @。&& npm runを使用して、カスタム引数をeslintに渡すために使用するeslint + tslint設定です。 tslint && echo 'lint clean!';}; f "
ecmanaut '25

3
"myPackage:myPort 9090"の値を設定するより良い方法は、コマンド "--myPackage:myPort = 9090"-keithcirkel.co.uk/how-to-use-npm-as-a-buildに構成フラグを使用することです。 -tool
chrismarx

223

あなたはのような ものを実行できるように頼みましたnpm start 8080。これはscript.js、次のようにファイルを変更したり構成ファイルを作成したりすることなく可能です。

たとえば、"scripts"JSON値に以下を含めます。

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

そして、コマンドラインから:

$ PORT=8080 npm start

これがbashとnpm 1.4.23を使用して動作することを確認しました。この回避策では、GitHub npmの問題#3494を解決する必要がないことに注意してください。


19
これは本当にうまくいきます。node ./script.js server ${PORT:-8080}オプションにすることもできます。
graup

7
git bashを使用しているWindowsではこれを実行できないようです。誰かが多分それを働かせましたか?(ubuntuでも同じコマンドが機能します)
KarolisŠarapnickis16年

3
ちょっと@graupこれは私にとってはNODE_PORT=${PORT=8080}うまくいきましたが(等しいことに注意してください)、:-構文は
うまくいき

14
これはクロスプラットフォームでは機能しません!たとえば、Windowsではコマンドはである必要がありますnode ./script.js server %PORT%cross-varcross-envの使用を検討してください。
Stijn de Witt

env varsをcli argsとして使用するユースケースは、私にかなり制限されているようですか?設定モジュールのようなものを使用して、環境変数、デフォルト、一般的な設定を処理することもできます。
Mr5o1 2018

93

あなたもそれをすることができます:

package.json

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

cool.js

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

CLIの場合:

npm --myVar=something run-script cool

出力する必要があります:

{ myVar: 'something' }

更新:npm 3.10.3を使用すると、process.env.npm_config_変数が小文字になっているように見えますか?私はも使用better-npm-runしているので、これがバニラのデフォルトの動作であるかどうかはわかりませんが、この答え機能しています。の代わりにprocess.env.npm_config_myVarprocess.env.npm_config_myvar


4
これは私のために働いてくれてありがとう!具体的には、コマンドラインで指定している変数名の「npm_config_」プレフィックスが欠落していたもの。
jp093121 2015年

2
これは間違っています。process.env.npm_config_myVar値ではなく、trueを返します。
Karl Morrison、

1
npmバージョン6.8.0で動作しますが、変数名に小文字を使用した場合のみです。それはlilke npmを小文字に変更するように見えます
Ofir Meguri


78

jakub.gの答えは正しいですが、gruntを使用した例は少し複雑に見えます。

だから私の簡単な答え:

-コマンドライン引数をnpmスクリプトに送信する

コマンドライン引数をnpmスクリプトに送信する構文:

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

webpack開発サーバーを開始するために、package.jsonにnpm開始タスクがあるとします。

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

これをコマンドラインから実行します npm start

ここで、ポートをnpmスクリプトに渡したい場合は、次のようにします。

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

これを実行し、コマンドラインを介して5000などのポートを渡すと、次のようになります。

npm start --port:5000

-package.json設定を使用:

jakub.gで言及されているように、package.jsonの設定でパラメータを設定することもできます

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

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

npm start 設定で指定されたポートを使用するか、またはそれを上書きすることができます

npm config set myPackage:myPort 3000

-npmスクリプトでパラメーターを設定する

npmスクリプトで設定された変数を読み取る例。この例ではNODE_ENV

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

prodまたはdevのいずれかでserver.jsの NODE_ENVを読み取る

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

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

5
以下のような構文というノート"start:prod": "NODE_ENV=prod node server.js"package.jsonWindows上では動作しません、あなたが使用しない限り、クロスのenv
jakub.g

2
修正?: このチュートリアルで説明されている私の使用法に従う"start": "webpack-dev-server --port process.env.npm_package_config_myPort || 8080" },必要があります。プロセスrefは明らかにJavaScript内で使用できます。"start": "webpack-dev-server --port $npm_package_config_myPort || 8080" },
アーロンローラー


34

process.argvコードで使用し、$*スクリプトの値エントリの末尾を提供します。

例として、提供された引数を標準出力に記録するだけの簡単なスクリプトで試してくださいechoargs.js

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

package.json:

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

例:

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

process.argv[0]は実行可能ファイル(ノード)でprocess.argv[1]あり、スクリプトです。

npm v5.3.0およびノー​​ドv8.4.0でテスト済み


追加した後に動作しません。--例えば、引数に- npm run demo.js --skip余分を追加した場合、それは動作します--例えば、 -npm run demo.js -- --skip
Shreyas

別のechoargs.jsスクリプトファイルがなくてもこの方法を使用できますか?
Joshua Pinter

@JoshuaPinter echoargs.jsは単なる例であり、これを明確にするために回答を編集します
Peter

@ピーターそうですが、スクリプトファイルである必要があります。を使用adb.dbてAndroidエミュレーターにファイルをプッシュし、プッシュするファイルのローカルパスの.dbパラメーターを受け入れるスクリプトを作成しようとしていますadb push。これは、の最初のパラメーターです。このような何か:"db:push": "adb push process.argv.slice(2) /data/data/com.cntral.app/databases/database.db"と呼び出したいですnpm run db:push /Users/joshuapinter/Downloads/updated.db。何かご意見は?
Joshua Pinter

21

引数を単に末尾に追加するのではなく、npmスクリプトの途中に渡す場合、インライン環境変数は適切に機能するように見えます。

"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",
},

ここでnpm run devは、-w監視フラグをbabel に渡しnpm run startますが、通常のビルドを1回だけ実行します。


これはCLIからどのように呼び出されますか?
2015

@dresdin npm run devnpm start
TJ

2
Windowsで使用するには、クロス環境を使用する必要があります。
fracz 2016年

8

私は過去にこのワンライナーを使用していましたが、少し時間が経過した後、Node.jsは最近それを再発見する必要がありました。@francoisrvで言及されているソリューションと同様に、node_config_*変数を利用します。

次の最小限のpackage.jsonファイルを作成します。

{
  "name": "argument",
  "version": "1.0.0",
  "scripts": {
    "argument": "echo \"The value of --foo is '${npm_config_foo}'\""
  }
}

次のコマンドを実行します。

npm run argument --foo=bar

次の出力を確認します。

--fooの値は「bar」です

これらすべてはnpm公式ドキュメントにうまく文書化されています:

注:環境変数」の見出しは、スクリプト内の変数の動作が、ドキュメントで定義されているものとは異なることを説明しています。これは、大文字と小文字を区別する場合や、引数がスペースまたは等号で定義されている場合にも当てはまります。

注:ハイフンを含む引数を使用している場合、これらは対応する環境変数でアンダースコアに置き換えられます。たとえば、npm run example --foo-bar=bazに対応し${npm_config_foo_bar}ます。

注:非WSL Windowsユーザーの場合は、以下の... TL @Doctorブルーのコメントを参照してください。DRは交換してください${npm_config_foo}%npm_config_foo%


こんにちは。私はあなたの例を使用しようとしていますが、それは私のために機能していないと思います。「引数」スクリプトをコピーして貼り付け、コマンド(npm run argument --foo=bar)を実行するために同じことを行いましたが、変数は置き換えられません:"The value of --foo is '${npm_config_foo}'"。NPMのバージョン6.9.0が必要な場合は、Windows 10で実行します。
Blue Blue

@DoctorBlueああ、そうですね、NodeとWindowsはいつもうまくいくとは限りません...この記事は、npmスクリプトの環境変数にいくつかの光を当てるかもしれません:(TL; DRコマンドは、別のシェルから起動された場合でも、ホストOSに直接行きます)ブログ.risingstack.com / node-js-windows-10-tutorial /…設定がよくわかりませんが、Git Bashを使用してNodeを実行している場合は、WSLから実行することを検討してください:) docs。 microsoft.com/en-us/windows/nodejs/setup-on-wsl2
Andrew Odri

1
私はそれを考え出した。%npm_config_foo%代わりに使用する必要がありました。純粋なWindowsコマンドライン/ Powershellはこちら。(選択肢もありません。)
ドクターブルー

6

これは実際にはあなたの質問には答えませんが、代わりに常に環境変数を使用できます:

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

次に、server.jsファイルで:

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

1
これは、UNIXプラットフォームを使用している場合に適しています。残念ながら、独自の規則があるため、Windowsでは機能しません。
JuhoVepsäläinen15年

6

上記の答えのほとんどは、npmによって呼び出されるNodeJSスクリプトに引数を渡すだけです。私の解決策は一般的な使用のためのものです。

npmスクリプトをシェルインタープリター(例:) sh呼び出しでラップし、通常どおり引数を渡します。唯一の例外は、最初の引数番号がであること0です。

たとえば、NPMのスクリプトを追加したいsomeprogram --env=<argument_1>someprogramただの値出力しenv、引数を:

package.json

"scripts": {
  "command": "sh -c 'someprogram --env=$0'"
}

実行すると:

% npm run -s command my-environment
my-environment

ありがとう!これは完璧でした!
Felipe Desiderati

シンプルでエレガント!MS DOSシェルでは動作しません。
n370

3

私が見るところによると、人々はスクリプトをより簡単に実行したいときにpackage.jsonスクリプトを使用します。たとえばnodemon、ローカルのnode_modulesにインストールされているものを使用nodemonするには、cliから直接呼び出すことはできませんが、を使用して呼び出すことはできます./node_modules/nodemon/nodemon.js。したがって、この長いタイピングを簡単にするために、これを置くことができます...

    ...

    スクリプト:{
      「開始」:「nodemon app.js」
    }

    ...

...次にnpm start、最初の引数としてapp.jsを持つ「nodemon」を使用するように呼び出します。

私が言おうとしていることは、nodeコマンドでサーバーを起動したいだけなら、を使用する必要はないと思いますscripts。タイピングnpm startまたはnode app.js同じ努力をしています。

ただし、を使用しnodemon、動的な引数を渡したい場合は、scriptどちらも使用しないでください。代わりにsymlinkを使用してみてください。

たとえば、での移行の使用sequelize。シンボリックリンクを作成します...

ln -s node_modules/sequelize/bin/sequelize sequelize

...そして、私はそれを呼ぶとき、私はどんな議論も渡すことができます...

./sequlize -h /* show help */

./sequelize -m /* upgrade migration */

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

等...

現時点では、symlinkを使用するのが最善の方法ですが、それがベストプラクティスであるとは思えません。

私の回答に対するあなたの意見も期待しています。


1
これはまったく質問に答えません。どうして6つの賛成票を得たのかはわかりませんが、おめでとうございます:)
Dan Dascalescu

2

注:このアプローチはpackage.jsonオンザフライで変更します。代替手段がない場合は、この方法を使用します。

コマンドライン引数をスクリプトに渡さなければなりませんでした。

"scripts": {
    "start": "npm run build && npm run watch",
    "watch": "concurrently  \"npm run watch-ts\" \"npm run watch-node\"",
    ...
}

つまり、これはアプリをで起動することを意味しnpm run startます。

ここで、引数を渡したい場合は、多分次のように始めます。

npm run start -- --config=someConfig

これは次のことを行いnpm run build && npm run watch -- --config=someConfigます。これの問題は、スクリプトの最後に常に引数を追加することです。これは、すべてのチェーンされたスクリプトがこれらの引数を取得しないことを意味します(Argsは、すべてまたは必要ではないかもしれませんが、それは別の話です)。さらに、リンクされたスクリプトが呼び出されると、それらのスクリプトは渡された引数を取得しません。つまり、watchスクリプトは渡された引数を取得しません。

私のアプリの本番使用はとして行われる.exeため、exeで引数を渡すと正常に機能しますが、開発中にこれを実行したい場合、問題が発生します。

これを達成するための適切な方法を見つけることができなかったので、これは私が試したものです。

私はjavascriptファイルを作成しました。start-script.jsアプリケーションの親レベルに「default.package.json」があり、「package.json」を維持する代わりに「default.package.json」を維持しています。の目的start-script.jsonは、を読み取ってdefault.package.json抽出しscripts、検索してnpm run scriptname、渡された引数をこれらのスクリプトに追加することです。この後、新しいpackage.jsonスクリプトを作成し、変更されたスクリプトでdefault.package.jsonからデータをコピーして、を呼び出しますnpm run start

const fs = require('fs');
const { spawn } = require('child_process');

// open default.package.json
const defaultPackage = fs.readFileSync('./default.package.json');
try {
    const packageOb = JSON.parse(defaultPackage);
    // loop over the scripts present in this object, edit them with flags
    if ('scripts' in packageOb && process.argv.length > 2) {

        const passedFlags = ` -- ${process.argv.slice(2).join(' ')}`;
        // assuming the script names have words, : or -, modify the regex if required.
        const regexPattern = /(npm run [\w:-]*)/g;
        const scriptsWithFlags = Object.entries(packageOb.scripts).reduce((acc, [key, value]) => {
            const patternMatches = value.match(regexPattern);
            // loop over all the matched strings and attach the desired flags.
            if (patternMatches) {
                for (let eachMatchedPattern of patternMatches) {
                    const startIndex = value.indexOf(eachMatchedPattern);
                    const endIndex = startIndex + eachMatchedPattern.length;
                    // save the string which doen't fall in this matched pattern range.
                    value = value.slice(0, startIndex) + eachMatchedPattern + passedFlags + value.slice(endIndex);
                }
            }
            acc[key] = value;
            return acc;
        }, {});
        packageOb.scripts = scriptsWithFlags;
    }

    const modifiedJSON = JSON.stringify(packageOb, null, 4);
    fs.writeFileSync('./package.json', modifiedJSON);

    // now run your npm start script
    let cmd = 'npm';
    // check if this works in your OS
    if (process.platform === 'win32') {
        cmd = 'npm.cmd';    // https://github.com/nodejs/node/issues/3675
    }
    spawn(cmd, ['run', 'start'], { stdio: 'inherit' });

} catch(e) {
    console.log('Error while parsing default.package.json', e);
}

今、代わりにnpm run start、私はnode start-script.js --c=somethis --r=somethingElse

最初の実行は問題ないように見えますが、完全にはテストされていません。アプリの開発に使用したい場合は、それを使用してください。


1

sequelize seed:generate cliコマンドを実行して問題を解決しようとしたときに、この質問を見つけました。

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

要点を述べましょう。package.jsonファイルに短いスクリプトコマンドを含めると同時に--name引数を指定したかった

答えはいくつかの実験の後に来ました。これがpackage.jsonの私のコマンドです

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

...そして、これはターミナルで実行してユーザーのシードファイルを生成する例です

> yarn seed:generate --name=user

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

ご参考までに

yarn -v
1.6.0

npm -v
5.6.0

2
これは、2013年に承認された回答で説明されている手法と同じ-- --arg1, ...ですか。
Dan Dascalescu、

2
では、なぜ答えを繰り返すのでしょうか?
Dan Dascalescu、

私は明確な使用例を共有しました、それは明白ではありませんか?
Serge Seletskyy

2
別の回答ですでに説明されている手法の別の例を共有したい場合は、その回答にコメントとして私の例を追加します。
Dan Dascalescu、

1
ゴチャ、次回はそうする
セルジュ・セレツキー

0

npm run script_target-<argument>基本的にこれはコマンドライン引数を渡す方法ですが、コマンドを実行しているようにスクリプトが1つのコマンドしか実行していない場合にのみ機能します。つまり、npm run start-4200

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

これはコマンドラインパラメーターを渡すために実行されますが、npm run build c:/ workspace / fileのように複数のコマンドを一緒に実行するとどうなるでしょうか。

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

しかし、copy c:/ file && ng build c:/ work space / fileを実行している間は、このように解釈 され、このcopy c:/ file c:/ work space / file && ng buildのようなものが期待され ます

注:-コマンドラインパラメータは、スクリプト内のコマンドが1つだけの場合にのみ機能します。

上記のいくつかの回答を読みましたが、$記号を使用してコマンドラインパラメータにアクセスできると書かれているものもありますが、これは機能しません


0

すでに承認済みの回答があることは知っていますが、私はこのJSONアプローチが好きです。

npm start '{"PROJECT_NAME_STR":"my amazing stuff", "CRAZY_ARR":[0,7,"hungry"], "MAGICAL_NUMBER_INT": 42, "THING_BOO":true}';

通常、プロジェクト名など、必要な変数が1つあるので、これは簡単なことです。

また、私はしばしばpackage.jsonにこのようなものを持っています

"scripts": {
    "start": "NODE_ENV=development node local.js"
}

そして、貪欲な私は「すべて」、NODE_ENV 、および CMD行の引数を必要としています。

あなたは単にあなたのファイル(私の場合はlocal.js)でこれらのようなものにアクセスします

console.log(process.env.NODE_ENV, starter_obj.CRAZY_ARR, starter_obj.PROJECT_NAME_STR, starter_obj.MAGICAL_NUMBER_INT, starter_obj.THING_BOO);

あなたはちょうどこのビットを上に置く必要があります(私はv10.16.0 btwを実行しています)

var starter_obj = JSON.parse(JSON.parse(process.env.npm_config_argv).remain[0]);

Anyhoo、質問はすでに回答済みです。この方法をよく使うので、共有したいと思いました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.