سؤال

كيف يمكنني استخدام الإصدار المحلي من الوحدة النمطية في node.js.على سبيل المثال، في تطبيقي، قمت بتثبيت Coffee-script:

npm install coffee-script

هذا تثبيته في ./node_modules وأمر القهوة موجود ./node_modules/.bin/coffee.هل هناك طريقة لتشغيل هذا الأمر عندما أكون في المجلد الرئيسي لمشروعي؟أعتقد أنني أبحث عن شيء مماثل ل bundle exec في المجمع.في الأساس، أود تحديد نسخة من نص القهوة الذي يجب على جميع المشاركين في المشروع استخدامه.

أعلم أنه يمكنني إضافة -g علم بتثبيته عالميًا حتى تعمل القهوة بشكل جيد في أي مكان، ولكن ماذا لو أردت الحصول على إصدارات مختلفة من القهوة لكل مشروع؟

هل كانت مفيدة؟

المحلول

تحديث:كما يشير Seyeong Jeong في إجابته أدناه، منذ npm 5.2.0 يمكنك استخدامه npx [command], ، وهو أكثر ملاءمة.

الإجابة القديمة للإصدارات قبل 5.2.0:

المشكلة مع وضع

./node_modules/.bin

في PATH الخاص بك هو أنه يعمل فقط عندما يكون دليل العمل الحالي الخاص بك هو جذر بنية دليل المشروع الخاص بك (أي.موقع node_modules)

بغض النظر عن دليل العمل الخاص بك، يمكنك الحصول على مسار الثنائيات المثبتة محليًا باستخدام

npm bin

لتنفيذ تثبيت محليا coffee ثنائي مستقل عن مكان وجودك في التسلسل الهرمي لدليل المشروع، يمكنك استخدام بنية bash هذه

PATH=$(npm bin):$PATH coffee

لقد قمت باستبدال هذا بـ npm-exec

alias npm-exec='PATH=$(npm bin):$PATH'

لذا، الآن أستطيع

npm-exec coffee

لتشغيل النسخة الصحيحة من القهوة بغض النظر عن مكان وجودي

$ pwd
/Users/regular/project1

$ npm-exec which coffee
/Users/regular/project1/node_modules/.bin/coffee

$ cd lib/
$ npm-exec which coffee
/Users/regular/project1/node_modules/.bin/coffee

$ cd ~/project2
$ npm-exec which coffee
/Users/regular/project2/node_modules/.bin/coffee

نصائح أخرى

Nice example

ليس عليك التلاعب $PATH أي أكثر من ذلك!

من npm@5.2.0, npm السفن مع npx الحزمة التي تتيح لك تشغيل الأوامر من ملف محلي node_modules/.bin أو من ذاكرة التخزين المؤقت المركزية.

ببساطة قم بتشغيل:

$ npx [options] <command>[@version] [command-arg]...

بشكل افتراضي، npx سوف تحقق ما إذا كان <command> موجود في $PATH, ، أو في ثنائيات المشروع المحلي، وقم بتنفيذ ذلك.

الاتصال npx <command> متى <command> ليس بالفعل في الخاص بك $PATH سيقوم تلقائيًا بتثبيت حزمة بهذا الاسم من سجل NPM لك، واستدعاءها.عند الانتهاء من ذلك، لن تكون الحزمة المثبتة في أي مكان في عوالمك، لذلك لن تضطر إلى القلق بشأن التلوث على المدى الطويل.يمكنك منع هذا السلوك من خلال توفير --no-install خيار.

ل npm < 5.2.0, ، يمكنك التثبيت npx الحزمة يدويًا عن طريق تشغيل الأمر التالي:

$ npm install -g npx

استخدم ال npm bin للحصول على دليل العقدة /bin لمشروعك

$ $(npm bin)/<binary-name> [args]

على سبيل المثال

$ $(npm bin)/bower install

يستخدم npm run[-script] <script name>

بعد استخدام npm لتثبيت حزمة bin على ملفك المحلي ./node_modules الدليل، تعديل package.json لإضافة <script name> مثله:

$ npm install --save learnyounode
$ edit packages.json
>>> in packages.json
...
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "learnyounode": "learnyounode"
},
...
$ npm run learnyounode

سيكون من الرائع أن يكون تثبيت npm يحتوي على خيار --add-script أو شيء من هذا القبيل أو إذا كان تشغيل npm سيعمل دون إضافة إلى كتلة البرامج النصية.

يستخدم npm-run.

من التمهيدي:

تشغيل npm

ابحث عن الملفات التنفيذية المحلية وقم بتشغيلها منNode_modules

أي ملف قابل للتنفيذ متاح لبرنامج نصي لدورة حياة npm متاح لـ npm-run.

الاستخدام

$ npm install mocha # mocha installed in ./node_modules
$ npm-run mocha test/* # uses locally installed mocha executable 

تثبيت

$ npm install -g npm-run

تحديث: لم أعد أوصي بهذه الطريقة، لأسباب أمنية مذكورة وليس الأحدث npm bin يأمر.الإجابة الأصلية أدناه:

كما اكتشفت، توجد أي ثنائيات مثبتة محليًا ./node_modules/.bin.من أجل تشغيل الثنائيات دائمًا في هذا الدليل بدلاً من الثنائيات المتاحة عالميًا، إذا كانت موجودة، أقترح عليك وضعها ./node_modules/.bin الأول في طريقك:

export PATH="./node_modules/.bin:$PATH"

إذا وضعت هذا في الخاص بك ~/.profile, coffee سوف يكون دائما ./node_modules/.bin/coffee إذا كان متاحا، وإلا /usr/local/bin/coffee (أو أي بادئة تقوم بتثبيت وحدات العقدة تحتها).

يواجه حل PATH مشكلة تتمثل في أنه إذا تم وضع $(npm bin) في .profile/.bashrc/etc، فسيتم تقييمه مرة واحدة ويتم تعيينه إلى الأبد على أي دليل تم تقييم المسار فيه لأول مرة.إذا قمت بدلاً من ذلك بتعديل المسار الحالي، ففي كل مرة تقوم فيها بتشغيل البرنامج النصي، سينمو المسار الخاص بك.

للتغلب على هذه المشكلات، قمت بإنشاء وظيفة واستخدمتها.لا يعدل بيئتك وهو سهل الاستخدام:

function npm-exec {
   $(npm bin)/$@  
}

يمكن بعد ذلك استخدام هذا على النحو التالي دون إجراء أي تغييرات على بيئتك:

npm-exec r.js <args>

إذا كنت تريد الاحتفاظ بـ npm، إذن npx يجب أن تفعل ما تحتاجه.


إذا كان التبديل إلى الغزل (استبدال npm بواسطة facebook) خيارًا متاحًا لك، فيمكنك الاتصال بـ:

 yarn yourCmd

ستحظى البرامج النصية الموجودة داخل الحزمة.json بالأولوية، وإذا لم يتم العثور على أي منها، فسيتم البحث داخل الملف ./node_modules/.bin/ مجلد.

كما أنه يخرج ما تم تشغيله:

$ yarn tsc
yarn tsc v0.27.5
$ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"

لذلك ليس عليك إعداد البرامج النصية لكل أمر في ملفك package.json.


إذا كان لديك برنامج نصي محدد في .scripts داخل الخاص بك package.json:

"tsc": "tsc" // each command defined in the scripts will be executed from `./node_modules/.bin/` first

yarn tsc سيكون معادلاً ل yarn run tsc أو npm run tsc:

 yarn tsc
 yarn tsc v0.27.5
 $ tsc

تحديث:إذا كنت تستخدم npm الأخير (الإصدار> 5.2)

يمكنك استخدام:

npx <command>

npx يبحث عن الأمر في .bin الدليل إذا كان لديك node_modules

الجواب القديم:

للنوافذ

قم بتخزين ما يلي في ملف يسمى npm-exec.bat وإضافته إلى الخاص بك %PATH%

@echo off
set cmd="npm bin"
FOR /F "tokens=*" %%i IN (' %cmd% ') DO SET modules=%%i
"%modules%"\%*

الاستخدام

ثم يمكنك استخدامه مثلnpm-exec <command> <arg0> <arg1> ...

على سبيل المثال

ينفذ wdio المثبتة في دليل العقدة المحلية، قم بما يلي:

npm-exec wdio wdio.conf.js

أي.سيتم تشغيله .\node_modules\.bin\wdio wdio.conf.js

أفضل عدم الاعتماد على الأسماء المستعارة لـ Shell أو أي حزمة أخرى.

إضافة خط بسيط إلى scripts قسم الخاص بك package.json, يمكنك تشغيل أوامر npm المحلية مثل

npm run webpack

package.json

{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "webpack": "webpack"
  },
  "devDependencies": {
    "webpack": "^4.1.1",
    "webpack-cli": "^2.0.11"
  }
}

إذا كنت تريد تحديث متغير PATH بشكل صحيح بناءً على دليل العمل الحالي لديك، فأضف هذا إلى نهاية ملفك .bashrc- ما يعادل (أو بعد أي شيء يحدد PATH):

__OLD_PATH=$PATH
function updatePATHForNPM() {
  export PATH=$(npm bin):$__OLD_PATH
}

function node-mode() {
  PROMPT_COMMAND=updatePATHForNPM
}

function node-mode-off() {
  unset PROMPT_COMMAND
  PATH=$__OLD_PATH
}

# Uncomment to enable node-mode by default:
# node-mode

قد يؤدي هذا إلى إضافة تأخير قصير في كل مرة يتم فيها عرض موجه bash (حسب حجم مشروعك، على الأرجح)، لذلك يتم تعطيله افتراضيًا.

يمكنك تمكينه وتعطيله داخل جهازك عن طريق التشغيل node-mode و node-mode-off, ، على التوالى.

لقد استخدمت دائمًا نفس الأسلوب الذي اتبعه @guneysus لحل هذه المشكلة، وهو إنشاء برنامج نصي في ملف package.json واستخدامه في تشغيل npm run script-name.

ومع ذلك، في الأشهر الأخيرة كنت أستخدمه npx و أنا أحبه.

على سبيل المثال، قمت بتنزيل مشروع Angular ولم أرغب في تثبيت Angular CLI عالميًا.لذلك، مع تثبيت npx، بدلاً من استخدام الأمر global angular cli (إذا كنت قد قمت بتثبيته) مثل هذا:

ng serve

يمكنني القيام بذلك من وحدة التحكم:

npx ng serve

وهنا مقال لقد كتبت عن NPX وهذا يتعمق أكثر في الأمر.

zxc يشبه "حزمة exec" لـnodejs.إنه مشابه للاستخدام PATH=$(npm bin):$PATH:

$ npm install -g zxc
$ npm install gulp
$ zxc which gulp
/home/nathan/code/project1/node_modules/.bin/gulp

نفس الحل المقبول @regular، لكن نكهة قشر السمك

if not contains (npm bin) $PATH
    set PATH (npm bin) $PATH
end

يمكنك أيضًا استخدام direnv وتغيير متغير PATH $ فقط في مجلد العمل الخاص بك.

$ cat .envrc
> export PATH=$(npm bin):$PATH

أضف هذا البرنامج النصي إلى .bashrc.ثم يمكنك الاتصال coffee أو أي شيء محليا.وهذا مفيد لجهاز الكمبيوتر المحمول الخاص بك، ولكن لا تستخدمه على الخادم الخاص بك.

DEFAULT_PATH=$PATH;

add_local_node_modules_to_path(){
  NODE_MODULES='./node_modules/.bin';
  if [ -d $NODE_MODULES ]; then
    PATH=$DEFAULT_PATH:$NODE_MODULES;
  else
    PATH=$DEFAULT_PATH;
  fi
}

cd () {
  builtin cd "$@";
  add_local_node_modules_to_path;
}

add_local_node_modules_to_path;

ملحوظة:هذا البرنامج النصي يصنع اسمًا مستعارًا لـ cd الأمر، وبعد كل مكالمة cd فإنه يتحقق node_modules/.bin وإضافته إلى الخاص بك $PATH.

ملاحظة 2:يمكنك تغيير السطر الثالث إلى NODE_MODULES=$(npm bin);.ولكن هذا من شأنه أن يجعل cd الأمر بطيء جدًا.

بالنسبة لنظام التشغيل Windows استخدم هذا:

/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version

لقد واجهت نفس المشكلة ولا أحب بشكل خاص استخدام الأسماء المستعارة (مثل عادي's المقترحة)، وإذا لم تعجبك أيضًا، فإليك حل بديل آخر أستخدمه، عليك أولاً إنشاء نص bash صغير قابل للتنفيذ، على سبيل المثال setenv.sh:

#!/bin/sh

# Add your local node_modules bin to the path
export PATH="$(npm bin):$PATH"

# execute the rest of the command
exec "$@"

وبعد ذلك يمكنك استخدام أي ملفات تنفيذية في ملفك المحلي /bin باستخدام هذا الأمر:

./setenv.sh <command>
./setenv.sh 6to5-node server.js
./setenv.sh grunt

إذا كنت تستخدم scripts في package.json ثم:

...,
scripts: {
    'start': './setenv.sh <command>'
}

أود أن أعرف ما إذا كانت هذه فكرة سيئة/غير آمنة، ولكن بعد التفكير فيها قليلاً، لا أرى مشكلة هنا:

تعديل حل Linus غير الآمن لإضافته إلى النهاية باستخدام npm bin للعثور على الدليل، وجعل البرنامج النصي يدعو فقط npm bin عندما package.json موجود في أحد الوالدين (للسرعة)، وهذا ما توصلت إليه zsh:

find-up () {
  path=$(pwd)
  while [[ "$path" != "" && ! -e "$path/$1" ]]; do
    path=${path%/*}
  done
  echo "$path"
}

precmd() {
  if [ "$(find-up package.json)" != "" ]; then
    new_bin=$(npm bin)
    if [ "$NODE_MODULES_PATH" != "$new_bin" ]; then
      export PATH=${PATH%:$NODE_MODULES_PATH}:$new_bin
      export NODE_MODULES_PATH=$new_bin
    fi
  else
    if [ "$NODE_MODULES_PATH" != "" ]; then
      export PATH=${PATH%:$NODE_MODULES_PATH}
      export NODE_MODULES_PATH=""
    fi
  fi
}

ل bash, ، بدلاً من استخدام precmd هوك، يمكنك استخدام $PROMPT_COMMAND متغير (لم أختبر هذا ولكنك حصلت على الفكرة):

__add-node-to-path() {
  if [ "$(find-up package.json)" != "" ]; then
    new_bin=$(npm bin)
    if [ "$NODE_MODULES_PATH" != "$new_bin" ]; then
      export PATH=${PATH%:$NODE_MODULES_PATH}:$new_bin
      export NODE_MODULES_PATH=$new_bin
    fi
  else
    if [ "$NODE_MODULES_PATH" != "" ]; then
      export PATH=${PATH%:$NODE_MODULES_PATH}
      export NODE_MODULES_PATH=""
    fi
  fi   
}

export PROMPT_COMMAND="__add-node-to-path"

أنا Windows المستخدم وهذا ما نجح بالنسبة لي:

// First set some variable - i.e. replace is with "xo"
D:\project\root> set xo="./node_modules/.bin/"

// Next, work with it
D:\project\root> %xo%/bower install

حظ سعيد.

في حال كنت تستخدم fish shell ولا تريد أن تضيف إلى $path لأسباب أمنية.يمكننا إضافة الوظيفة أدناه لتشغيل الملفات التنفيذية للعقدة المحلية.

### run executables in node_module/.bin directory
function n 
  set -l npmbin (npm bin)   
  set -l argvCount (count $argv)
  switch $argvCount
    case 0
      echo please specify the local node executable as 1st argument
    case 1
      # for one argument, we can eval directly 
      eval $npmbin/$argv
    case '*'
      set --local executable $argv[1]
      # for 2 or more arguments we cannot append directly after the $npmbin/ since the fish will apply each array element after the the start string: $npmbin/arg1 $npmbin/arg2... 
      # This is just how fish interoperate array. 
      set --erase argv[1]
      eval $npmbin/$executable $argv 
  end
end

الآن يمكنك تشغيل شيء مثل:

n coffee

أو المزيد من الحجج مثل:

n browser-sync --version

ملاحظة، إذا كنت bash المستخدم ، فإن إجابات @ Bob9630 هي الطريقة التي يجب اتباعها من خلال الاستفادة من bash $@, ، وهو غير متوفر في fishshell.

قم بتضمين Coffee-script في package.json مع الإصدار المحدد المطلوب في كل مشروع، وعادةً ما يكون كالتالي:

"dependencies":{
  "coffee-script": ">= 1.2.0"

ثم قم بتشغيل npm install لتثبيت التبعيات في كل مشروع.سيؤدي هذا إلى تثبيت الإصدار المحدد من برنامج Coffee-Script والذي سيكون متاحًا محليًا لكل مشروع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top