การส่งอาร์กิวเมนต์บรรทัดคำสั่งไปยังสคริปต์ 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: เป็นไปได้ที่จะส่ง args ไปnpm runที่ npm 2.0.0

ไวยากรณ์มีดังนี้:

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

เพื่อรับค่าพารามิเตอร์ดูคำถามนี้ สำหรับการอ่านพารามิเตอร์ชื่อก็อาจจะดีที่สุดในการใช้ห้องสมุดการแยกเช่นyargsหรือminimist ; nodejs exposes process.argvทั่วโลกที่มีค่าพารามิเตอร์บรรทัดคำสั่ง แต่นี่เป็น API ระดับต่ำ (อาร์เรย์ของสตริงที่คั่นด้วยช่องว่างตามที่จัดทำโดยระบบปฏิบัติการไปยังโหนดปฏิบัติการ)


แก้ไข 2013.10.03:ปัจจุบันไม่สามารถทำได้โดยตรง แต่มีปัญหาnpmเกี่ยวกับGitHub ที่เปิดขึ้นเพื่อใช้งานพฤติกรรมที่คุณต้องการ ดูเหมือนว่าฉันทามติจะต้องดำเนินการนี้ แต่ก็ขึ้นอยู่กับปัญหาอื่นที่จะแก้ไขก่อน


คำตอบเดิม:ในฐานะที่เป็นวิธีแก้ปัญหาบางอย่าง (แม้ว่าจะไม่สะดวกมาก) คุณสามารถทำดังนี้:

พูดชื่อแพคเกจของคุณจากการpackage.jsonมีmyPackageและคุณยังมี

"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 startจะใช้ 8080 อย่างไรก็ตามคุณสามารถกำหนดค่าได้ (ค่าจะถูกเก็บไว้npmในที่จัดเก็บข้อมูลภายใน):

npm config set myPackage:myPort 9090

จากนั้นเมื่อเรียกใช้npm startจะใช้ 9090 (ค่าเริ่มต้นจากการpackage.jsonแทนที่)


1
นอกจากนี้ยังทำงานได้อย่างสมบูรณ์พร้อมกับแพ็คเกจเช่นyargs; พารามิเตอร์ทั้งหมดหลังจาก--สามารถแยกวิเคราะห์ได้อย่างสมบูรณ์แบบในสคริปต์ของคุณ
โทมัส

11
AFAIKS นี่เป็นเพียงการเพิ่มพารามิเตอร์ไปยังจุดสิ้นสุดของสคริปต์ของคุณเท่านั้นหากคุณต้องการพารามิเตอร์ที่อยู่ตรงกลาง
สป็อค

108
-- --argsอึศักดิ์สิทธิ์ที่แปลก แต่ไม่เป็นไร
สิงหาคม

9
@Spock คุณสามารถใช้ฟังก์ชั่นเชลล์ นี่คือการตั้งค่า eslint + tslint ที่ฉันใช้เพื่ออนุญาตให้ส่ง args แบบกำหนดเองไปยัง eslint สำหรับ insance ผ่าน "npm run lint - -f unix": "lint": "f () {eslint -f codeframe $ @. && npm run tslint && echo 'lint clean!';}; f "
ecmanaut

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}เพื่อให้เป็นตัวเลือก
2559

7
ฉันดูเหมือนจะไม่สามารถทำสิ่งนี้ในหน้าต่างด้วยทุบตีคอมไพล์ ทุกคนทำให้มันทำงานอาจ? (คำสั่งเดียวกันใช้ได้กับ Ubuntu)
Karolis Šarapnickis

3
สวัสดี @graup สิ่งนี้ใช้ได้สำหรับฉันNODE_PORT=${PORT=8080}(สังเกตเท่ากัน) แต่ไม่ใช่: - ไวยากรณ์
MaieonBrix

14
สิ่งนี้ไม่ทำงานข้ามแพลตฟอร์ม! เช่นบน Windows node ./script.js server %PORT%คำสั่งจะต้อง พิจารณาใช้ข้าม varและข้าม env
Stijn de Witt

usecase สำหรับการใช้ env vars เนื่องจาก cli args นั้นค่อนข้าง จำกัด กับฉันไหม อาจใช้บางอย่างเช่นโมดูลปรับแต่งเพื่อจัดการ env vars, ค่าเริ่มต้นและการกำหนดค่าโดยทั่วไป
Mr5o1

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_myVarลองแทนprocess.env.npm_config_myvar


4
ขอบคุณมันใช้งานได้สำหรับฉัน! สิ่งที่ฉันหายไปโดยเฉพาะคำนำหน้า "npm_config_" กับชื่อตัวแปรที่คุณระบุในบรรทัดคำสั่ง
jp093121

2
นี่เป็นสิ่งที่ผิด process.env.npm_config_myVarผลตอบแทนจริงไม่ใช่ค่า
Karl Morrison

1
ทำงานได้กับ npm เวอร์ชั่น 6.8.0 แต่เมื่อฉันใช้ตัวพิมพ์เล็กสำหรับชื่อตัวแปร ดูเหมือน lilke npm เปลี่ยนเป็นตัวพิมพ์เล็ก
Ofir Meguri

ทางออกที่ดีใช้งานได้กับกรณีที่ต่ำกว่าในวันที่ 6.5.0
GavinBelson

78

jakub.gคำตอบของนั้นถูกต้อง แต่ตัวอย่างจากการใช้ grunt นั้นค่อนข้างซับซ้อน

ดังนั้นคำตอบที่ง่ายกว่าของฉัน:

- ส่งอาร์กิวเมนต์บรรทัดคำสั่งไปยังสคริปต์ npm

ไวยากรณ์สำหรับการส่งอาร์กิวเมนต์บรรทัดคำสั่งไปยังสคริปต์ npm:

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

ลองนึกภาพเรามีภารกิจเริ่มต้นในรอบต่อนาทีใน package.json เพื่อเริ่มต้นเซิร์ฟเวอร์ dev ของ webpack:

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

เราเรียกใช้จากบรรทัดคำสั่งด้วย npm start

ตอนนี้ถ้าเราต้องการส่งผ่านพอร์ตไปยังสคริปต์ npm:

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

ทำงานนี้และผ่านพอร์ตเช่น 5,000 ผ่านบรรทัดคำสั่งจะเป็นดังนี้:

npm start --port:5000

- ใช้ package.json config:

ตามที่กล่าวไว้โดยjakub.gคุณสามารถกำหนด params ใน config ของ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"
},

อ่าน NODE_ENV ในserver.jsทั้งprodหรือdev

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.jsonจะไม่ทำงานบน Windows เว้นแต่คุณจะใช้cross-env
jakub.g

2
การแก้ไข: "start": "webpack-dev-server --port process.env.npm_package_config_myPort || 8080" },ควรเป็น"start": "webpack-dev-server --port $npm_package_config_myPort || 8080" },ไปตามการใช้งานของฉันอธิบายโดยบทช่วยสอนนี้ กระบวนการอ้างอิงสามารถใช้ภายในจาวาสคริปต์ได้อย่างชัดเจน
Aaron Roller


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

@ 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ธงดูไปที่บาเบล แต่npm run startเพียงเรียกใช้งานสร้างปกติครั้งเดียว


สิ่งนี้เรียกได้จาก CLI อย่างไร
bwobst

@dresdin npm run dev,npm start
TJ

2
จำเป็นต้องใช้cross-envเพื่อใช้งานบน Windows
fracz

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 ดูความคิดเห็น @Doctor สีน้ำเงินด้านล่าง ... TL; DR แทนที่ด้วย${npm_config_foo}%npm_config_foo%


สวัสดี. ฉันพยายามที่จะใช้ตัวอย่างของคุณ แต่ฉันกลัวว่ามันจะไม่ทำงานสำหรับฉัน ผมคัดลอกวาง "โต้แย้ง" ของคุณสคริปต์และก็ทำเช่นเดียวกันสำหรับคำสั่งที่จะ run ( npm run argument --foo=bar) "The value of --foo is '${npm_config_foo}'"แต่ตัวแปรไม่ได้ถูกแทนที่: ทำงานบน Windows 10 หากมีความสำคัญกับรุ่น 6.9.0 ของ NPM
Doctor Blue

@DoctorBlue Ahh ถูกต้อง Node และ Windows อาจเล่นได้ไม่ดีนัก ... บทความนี้อาจทำให้เข้าใจถึงสภาพแวดล้อมของตัวแปรในสคริปต์ npm: (คำสั่ง TL; DR ตรงไปยังโฮสต์ OS แม้ว่าบล็อกจากเชลล์อื่น) .risingstack.com / node-js-windows-10-tutorial / …ฉันไม่แน่ใจเกี่ยวกับการตั้งค่าของคุณ แต่ถ้าคุณกำลังใช้ Git Bash เพื่อเรียกใช้ Node คุณอาจต้องการพิจารณาเรียกใช้ผ่าน WSL :) เอกสาร microsoft.com/en-us/windows/nodejs/setup-on-wsl2
Andrew Odri

1
ฉันคิดออก เพียงแค่ต้องใช้%npm_config_foo%แทน บรรทัดคำสั่ง Pure Power Windows / PowerShell ที่นี่ (ไม่มีทางเลือกเช่นกัน)
Doctor Blue

6

สิ่งนี้ไม่ได้ตอบคำถามของคุณ แต่คุณสามารถใช้ตัวแปรสภาพแวดล้อมแทน:

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

จากนั้นในไฟล์ server.js ของคุณ:

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

1
สิ่งนี้ดีตราบใดที่คุณอยู่บนแพลตฟอร์ม Unix น่าเสียดายที่มันใช้งานไม่ได้กับ Windows เนื่องจากเป็นแบบแผนของตัวเอง
Juho Vepsäläinen

6

คำตอบส่วนใหญ่ข้างต้นครอบคลุมเพียงแค่ส่งข้อโต้แย้งไปยังสคริปต์ NodeJS ของคุณที่เรียกโดย npm โซลูชันของฉันสำหรับใช้งานทั่วไป

เพียงแค่ตัดสคริปต์ npm ด้วยการเรียก shell interpreter (เช่น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แต่เราสามารถเรียกมันโดยใช้ ดังนั้นเพื่อให้การพิมพ์ยาวง่ายขึ้นเราสามารถใส่ ...

    ...

    สคริปต์: {
      'start': 'nodemon app.js'
    }

    ...

... จากนั้นเรียกnpm startใช้ 'nodemon' ซึ่งมี app.js เป็นอาร์กิวเมนต์แรก

สิ่งที่ฉันพยายามที่จะบอกว่าถ้าคุณเพียงต้องการที่จะเริ่มต้นเซิร์ฟเวอร์ของคุณด้วยคำสั่งผมไม่คิดว่าคุณต้องใช้node scriptsพิมพ์npm startหรือnode app.jsมีความพยายามเดียวกัน

แต่ถ้าคุณต้องการใช้nodemonและต้องการผ่านการโต้แย้งแบบไดนามิกอย่าใช้scriptอย่างใดอย่างหนึ่ง ลองใช้ symlink แทน

sequelizeยกตัวอย่างเช่นการใช้การโยกย้ายด้วย ฉันสร้าง symlink ...

ln -s node_modules/sequelize/bin/sequelize sequelize

... และฉันสามารถโต้แย้งได้เมื่อฉันเรียกมันว่า ...

./sequlize -h /* show help */

./sequelize -m /* upgrade migration */

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

ฯลฯ ...

ณ จุดนี้การใช้ symlink เป็นวิธีที่ดีที่สุดที่ฉันสามารถคิดได้ แต่ฉันไม่คิดว่ามันเป็นการปฏิบัติที่ดีที่สุด

ฉันหวังว่าความคิดเห็นของคุณต่อคำตอบของฉัน


1
นี่ไม่ได้ตอบคำถามเลย ผมไม่ทราบว่ามันมี 6 upvotes แต่ขอแสดงความยินดี :)
แดนดาสคเลสุ

2

หมายเหตุ:วิธีการนี้จะแก้ไขของคุณpackage.jsonทันทีใช้มันหากคุณไม่มีทางเลือกอื่น

ฉันต้องส่งอาร์กิวเมนต์บรรทัดคำสั่งไปยังสคริปต์ซึ่งมีลักษณะดังนี้:

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

ดังนั้นวิธีการนี้ฉันเริ่ม app npm run startของฉันด้วย

ตอนนี้ถ้าฉันต้องการผ่านการโต้แย้งฉันจะเริ่มด้วยบางที:

npm run start -- --config=someConfig

สิ่งนี้คือ: npm run build && npm run watch -- --config=someConfig. ปัญหานี้คือมันมักจะผนวกข้อโต้แย้งที่ส่วนท้ายของสคริปต์ ซึ่งหมายความว่าสคริปต์ที่ถูกล่ามโซ่ทั้งหมดจะไม่ได้รับอาร์กิวเมนต์เหล่านี้ (อาจจะเป็นหรืออาจจะไม่จำเป็นสำหรับทุกคน แต่นั่นเป็นเรื่องที่ต่างออกไป) นอกจากนี้เมื่อสคริปต์ที่เชื่อมโยงถูกเรียกใช้สคริปต์เหล่านั้นจะไม่ได้รับอาร์กิวเมนต์ที่ส่งผ่าน เช่นwatchสคริปต์จะไม่รับอาร์กิวเมนต์ที่ส่งผ่าน

การใช้งานการผลิตของแอพของฉันเป็นเช่น .exeนั้นดังนั้นการส่งผ่านข้อโต้แย้งใน exe ทำงานได้ดี แต่ถ้าต้องการทำสิ่งนี้ในระหว่างการพัฒนา

ฉันไม่พบวิธีที่เหมาะสมในการบรรลุเป้าหมายดังนั้นนี่คือสิ่งที่ฉันได้ลอง

ฉันได้สร้างไฟล์จาวาสคริปต์: 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

ฉันได้พบคำถามนี้ในขณะที่ฉันพยายามที่จะแก้ปัญหาของฉันด้วยการใช้เมล็ดสืบเนื่อง: สร้างคำสั่ง cli:

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

ให้ฉันไปที่จุด ฉันต้องการมีคำสั่งสคริปต์สั้น ๆ ในไฟล์package.jsonของฉันและเพื่อให้ - อาร์กิวเมนต์ชื่อในเวลาเดียวกัน

คำตอบมาจากการทดลองบางอย่าง นี่คือคำสั่งของฉันในpackage.json

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

... และนี่คือตัวอย่างของการรันในเทอร์มินัลเพื่อสร้างไฟล์ seed สำหรับผู้ใช้

> yarn seed:generate --name=user

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

FYI

yarn -v
1.6.0

npm -v
5.6.0

2
นี่เป็นเทคนิคเดียวกับที่อธิบายไว้ในคำตอบที่ได้รับการยอมรับในปี 2013 ว่าจะผ่าน-- --arg1, ...หรือไม่
Dan Dascalescu

2
ตกลงแล้วทำซ้ำคำตอบทำไม?
Dan Dascalescu

ฉันได้แชร์ตัวอย่างการใช้งานที่แตกต่างกันชัดเจนหรือไม่
Serge Seletskyy

2
หากฉันต้องการแบ่งปันตัวอย่างอื่นสำหรับเทคนิคที่อธิบายไว้แล้วในคำตอบที่ต่างออกไปฉันจะเพิ่มตัวอย่างของฉันเป็นความคิดเห็นในคำตอบนั้น
Dan Dascalescu

1
gotcha จะทำเช่นนั้นในครั้งต่อไป
Serge Seletskyy

0

npm run script_target - <argument>โดยทั่วไปนี่เป็นวิธีการส่งผ่านอาร์กิวเมนต์บรรทัดคำสั่ง แต่จะทำงานเฉพาะในกรณีที่เมื่อสคริปต์มีเพียงคำสั่งเดียวที่ทำงานเหมือนฉันกำลังเรียกใช้คำสั่งเช่น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 &&g ng build c: / work space / file และเราคาดหวังอะไรทำนองนี้ c: / file c: / พื้นที่ทำงาน / ไฟล์ && ng build

หมายเหตุ: - ดังนั้นพารามิเตอร์บรรทัดคำสั่งจะทำงานเฉพาะโฆษณาที่คาดหวังในกรณีที่มีเพียงหนึ่งคำสั่งในสคริปต์

ฉันอ่านคำตอบบางข้อด้านบนซึ่งบางคำกำลังเขียนว่าคุณสามารถเข้าถึงพารามิเตอร์บรรทัดคำสั่งโดยใช้สัญลักษณ์ $ แต่สิ่งนี้จะไม่ทำงาน


0

ฉันรู้ว่ามีคำตอบที่อนุมัติแล้ว แต่ฉันชอบวิธี JSON นี้

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

ฉันมักจะมี 1 var ฉันต้องการเช่นชื่อโครงการดังนั้นฉันจึงพบว่า n ง่ายนี้

นอกจากนี้ฉันมักจะมีสิ่งนี้ใน 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.