Встановлюйте залежності глобально та локально, використовуючи package.json


189

За допомогою npm ми можемо встановити модулі глобально, використовуючи -gопцію. Як ми можемо це зробити у файлі package.json?

Припустимо, це мої залежності у файлі package.json

"dependencies": {
    "mongoose": "1.4.0",
    "node.io" : "0.3.3",
    "jquery"  : "1.5.1",
    "jsdom"   : "0.2.0",
    "cron"    : "0.1.2"
  }

Коли я запускаюся npm install, я хочу node.ioбути встановленим лише в усьому світі, решта повинні бути встановлені локально. Чи є варіант для цього?


11
Ви не можете. Однак ви можете встановити "preferGlobal": trueвсередині package.json для модуля.
Райнос

так, я знаю про <code> вважаю за краще глобальний </code>, але це встановить усі залежності в усьому світі ... все одно Спасибі! Я здогадуюсь, немає такої функції ...
Мадхусудхан,

3
Я не думаю, що це робить. Він встановлює поточний модуль глобально. Якщо для індивідуальної залежності встановлено значення true, воно також може бути встановлене в усьому світі. Дійсно, вам слід просто запитати @isaacs у # node.js
Raynos,

3
Глобальні установки можуть призвести до пекла залежності. Скажімо, пакет A потребує версії 0.3.3 та пакета B версії 0.3.4, і обидва не працюють з іншою версією. Тоді вам знадобляться дві машини для розміщення двох пакетів.
nalply

6
жоден з цих коментарів не допомагає мені в цьому питанні ... було б добре, якщо ви коду покажіть мені більше, ніж просто "preferGlobal":true... я не знаю, куди це помістити в package.json. npmjs.org/doc/json.html Документація NPM говорить про те, що віддається перевагаGlobal для вашого власного пакету, і якщо встановити його, він змусить встановити ваш власний пакет як глобальний. здається, що більше керівництва, хоча.
PPPaul

Відповіді:


216

Нова примітка: Ви, мабуть, цього не хочете чи не потребуєте. Що ви, мабуть, хочете зробити, це просто помістити ці типи командних залежностей для складання / тестування тощо у devDependenciesрозділ свого пакета.json. Щоразу, коли ви використовуєте щось із scriptsпакета.json, ваші команди devDependitions (у node_modules / .bin) діють так, ніби вони перебувають на вашому шляху.

Наприклад:

npm i --save-dev mocha # Install test runner locally
npm i --save-dev babel # Install current babel locally

Потім у package.json:

// devDependencies has mocha and babel now

"scripts": {
  "test": "mocha",
  "build": "babel -d lib src",
  "prepublish": "babel -d lib src"
}

Тоді у вашому командному рядку ви можете запустити:

npm run build # finds babel
npm test # finds mocha

npm publish # will run babel first

Але якщо ви дійсно хочете встановити глобально, ви можете додати попередню інсталяцію в розділ сценаріїв пакета.json:

"scripts": {
  "preinstall": "npm i -g themodule"
}

Тож фактично мій npm install виконує npm install знову .. що дивно, але, здається, працює.

Примітка. Можливо, у вас виникнуть проблеми, якщо ви використовуєте найпоширенішу установку для встановлення npmглобального пакета вузлів sudo. Один із варіантів - змінити npmконфігурацію, щоб це не потрібно:

npm config set prefix ~/npm, додайте $ HOME / npm / bin до $ PATH, додавши export PATH=$HOME/npm/bin:$PATHдо свого ~/.bashrc.


3
Мені не вдалося з цим працювати npm i -g underscore-cli. це попереджає про неправильність роботи wd. wd означає робочий каталог, я думаю. коли я вручну це роблю в командному рядку, тоді справи йдуть добре, проте я вважаю за краще, якщо користувач міг би впоратися з установкою мого коду простоюnpm install
PPPaul

3
PPPaul - У мене була та сама проблема, коли я нещодавно спробував цю хитрість. Можливо, моя установка зараз інша, або вона працює лише з певними модулями. Інакше я думаю, що щось змінилося з npm?
Джейсон Лайвсі

9
На додаток до цього ви можете попередньо перевірити, чи пакет уже встановлений: npm list module -g || npm install module -gяк npm поверне належні значення виходу.
m90

3
@CMCDragonkai: Це справді має бути окремим питанням. Але, ви ставите свої команди в сценарій і вказуєте сценарій як команду для виконання (як "preinstall" : "scripts/preinstall.sh").
Ми всі Моніка

1
@CMCDragonkai сформулює їх &&, наприклад,npm install -g bower && npm install -g grunt-cli
Матсман

12

Через недоліки, описані нижче, я рекомендую дотримуватися прийнятої відповіді:

Використовуйте npm install --save-dev [package_name]потім виконувати скрипти з:

$ npm run lint
$ npm run build
$ npm test

Моя оригінальна, але не рекомендується відповідь.


Замість використання глобальної установки ви можете додати пакет до свого devDependencies( --save-dev), а потім запустити двійковий файл з будь-якого місця у вашому проекті:

"$(npm bin)/<executable_name>" <arguments>...

У вашому випадку:

"$(npm bin)"/node.io --help

Цей інженер надав npm-execпсевдонім як ярлик. Цей інженер використовує оболонку під назвою env.sh. Але я вважаю за краще використовувати $(npm bin)безпосередньо, щоб уникнути зайвих файлів чи налаштувань.

Хоча кожен виклик робить трохи більшим, він повинен просто працювати , запобігаючи:

  • потенційна залежність конфліктує з глобальними пакетами (@nalply)
  • потреба в sudo
  • необхідність встановлення префікса npm (хоча я все-таки рекомендую використовувати його)

Недоліки:

  • $(npm bin) не працюватиме в Windows.
  • Інструменти глибше у вашому дереві розробок не з’являться у npm binпапці. (Встановіть npm-run або npm - що їх знайти.)

Здається , кращим рішенням є розміщення загальних завдань (таких , як будівництво і Мінімізація) в розділі «сценарії» з ваших package.json, як показує вище Джейсон.


Додати псевдонім в вашому .bashrcлегко додати bin/каталог в PATHзмінну оточення: alias nodebin='export PATH=$(npm bin)/:$PATH'. Виконати, nodebinі тоді ви можете просто ввести свої команди, як зазвичай.
gitaarik

Я не знаю, чому це не працює для команд. Звичайно, вам потрібно налаштувати його, і якщо вам не подобається використовувати псевдонім, це ваш вибір. Але це не завадить використовувати його в команді.
gitaarik

9

Це трохи старе, але я зіткнувся з вимогою, ось ось рішення, яке я придумав.

Проблема:

Наша команда розробників підтримує багато продуктів .NET для веб-додатків, які ми переходимо до AngularJS / Bootstrap. VS2010 не піддається легко процесам збирання на замовлення, і мої розробники регулярно працюють над кількома випусками нашої продукції. Наш VCS - це Subversion (я знаю, я знаю. Я намагаюся перейти на Git, але мій настирливий маркетинговий персонал настільки вимогливий), і єдине рішення VS включає декілька окремих проектів. Мені потрібно було, щоб мої співробітники мали загальний метод ініціалізації середовища розробки без необхідності встановлювати одні й ті ж пакети Node (gulp, bower тощо) на одній машині.

TL; DR:

  1. Потрібна "npm install" для встановлення глобального середовища розробки Node / Bower, а також усіх необхідних локальних пакетів для продукту .NET.

  2. Глобальні пакети повинні бути встановлені лише в тому випадку, якщо вони ще не встановлені.

  3. Локальні посилання на глобальні пакети повинні створюватися автоматично.

Рішення:

У нас вже є спільна рамка розробки, якою поділяються всі розробники та всі продукти, тому я створив сценарій NodeJS для встановлення глобальних пакетів при необхідності та створення локальних посилань. Сценарій знаходиться в ".... \ SharedFiles" щодо базової папки продукту:

/*******************************************************************************
* $Id: npm-setup.js 12785 2016-01-29 16:34:49Z sthames $
* ==============================================================================
* Parameters: 'links' - Create links in local environment, optional.
* 
* <p>NodeJS script to install common development environment packages in global
* environment. <c>packages</c> object contains list of packages to install.</p>
* 
* <p>Including 'links' creates links in local environment to global packages.</p>
* 
* <p><b>npm ls -g --json</b> command is run to provide the current list of 
* global packages for comparison to required packages. Packages are installed 
* only if not installed. If the package is installed but is not the required 
* package version, the existing package is removed and the required package is 
* installed.</p>.
*
* <p>When provided as a "preinstall" script in a "package.json" file, the "npm
* install" command calls this to verify global dependencies are installed.</p>
*******************************************************************************/
var exec = require('child_process').exec;
var fs   = require('fs');
var path = require('path');

/*---------------------------------------------------------------*/
/* List of packages to install and 'from' value to pass to 'npm  */
/* install'. Value must match the 'from' field in 'npm ls -json' */
/* so this script will recognize a package is already installed. */
/*---------------------------------------------------------------*/
var packages = 
  {
  "bower"                      :                      "bower@1.7.2", 
  "event-stream"               :               "event-stream@3.3.2",
  "gulp"                       :                       "gulp@3.9.0",
  "gulp-angular-templatecache" : "gulp-angular-templatecache@1.8.0",
  "gulp-clean"                 :                 "gulp-clean@0.3.1", 
  "gulp-concat"                :                "gulp-concat@2.6.0",
  "gulp-debug"                 :                 "gulp-debug@2.1.2",
  "gulp-filter"                :                "gulp-filter@3.0.1",
  "gulp-grep-contents"         :         "gulp-grep-contents@0.0.1",
  "gulp-if"                    :                    "gulp-if@2.0.0", 
  "gulp-inject"                :                "gulp-inject@3.0.0", 
  "gulp-minify-css"            :            "gulp-minify-css@1.2.3",
  "gulp-minify-html"           :           "gulp-minify-html@1.0.5",
  "gulp-minify-inline"         :         "gulp-minify-inline@0.1.1",
  "gulp-ng-annotate"           :           "gulp-ng-annotate@1.1.0",
  "gulp-processhtml"           :           "gulp-processhtml@1.1.0",
  "gulp-rev"                   :                   "gulp-rev@6.0.1",
  "gulp-rev-replace"           :           "gulp-rev-replace@0.4.3",
  "gulp-uglify"                :                "gulp-uglify@1.5.1",
  "gulp-useref"                :                "gulp-useref@3.0.4",
  "gulp-util"                  :                  "gulp-util@3.0.7",
  "lazypipe"                   :                   "lazypipe@1.0.1",
  "q"                          :                          "q@1.4.1",
  "through2"                   :                   "through2@2.0.0",

  /*---------------------------------------------------------------*/
  /* fork of 0.2.14 allows passing parameters to main-bower-files. */
  /*---------------------------------------------------------------*/
  "bower-main"                 : "git+https://github.com/Pyo25/bower-main.git" 
  }

/*******************************************************************************
* run */
/**
* Executes <c>cmd</c> in the shell and calls <c>cb</c> on success. Error aborts.
* 
* Note: Error code -4082 is EBUSY error which is sometimes thrown by npm for 
* reasons unknown. Possibly this is due to antivirus program scanning the file 
* but it sometimes happens in cases where an antivirus program does not explain 
* it. The error generally will not happen a second time so this method will call 
* itself to try the command again if the EBUSY error occurs.
* 
* @param  cmd  Command to execute.
* @param  cb   Method to call on success. Text returned from stdout is input.
*******************************************************************************/
var run = function(cmd, cb)
  {
  /*---------------------------------------------*/
  /* Increase the maxBuffer to 10MB for commands */
  /* with a lot of output. This is not necessary */
  /* with spawn but it has other issues.         */
  /*---------------------------------------------*/
  exec(cmd, { maxBuffer: 1000*1024 }, function(err, stdout)
    {
    if      (!err)                   cb(stdout);
    else if (err.code | 0 == -4082) run(cmd, cb);
    else throw err;
    });
  };

/*******************************************************************************
* runCommand */
/**
* Logs the command and calls <c>run</c>.
*******************************************************************************/
var runCommand = function(cmd, cb)
  {
  console.log(cmd);
  run(cmd, cb);
  }

/*******************************************************************************
* Main line
*******************************************************************************/
var doLinks  = (process.argv[2] || "").toLowerCase() == 'links';
var names    = Object.keys(packages);
var name;
var installed;
var links;

/*------------------------------------------*/
/* Get the list of installed packages for   */
/* version comparison and install packages. */
/*------------------------------------------*/
console.log('Configuring global Node environment...')
run('npm ls -g --json', function(stdout)
  {
  installed = JSON.parse(stdout).dependencies || {};
  doWhile();
  });

/*--------------------------------------------*/
/* Start of asynchronous package installation */
/* loop. Do until all packages installed.     */
/*--------------------------------------------*/
var doWhile = function()
  {
  if (name = names.shift())
    doWhile0();
  }

var doWhile0 = function()
  {
  /*----------------------------------------------*/
  /* Installed package specification comes from   */
  /* 'from' field of installed packages. Required */
  /* specification comes from the packages list.  */
  /*----------------------------------------------*/
  var current  = (installed[name] || {}).from;
  var required =   packages[name];

  /*---------------------------------------*/
  /* Install the package if not installed. */
  /*---------------------------------------*/
  if (!current)
    runCommand('npm install -g '+required, doWhile1);

  /*------------------------------------*/
  /* If the installed version does not  */
  /* match, uninstall and then install. */
  /*------------------------------------*/
  else if (current != required)
    {
    delete installed[name];
    runCommand('npm remove -g '+name, function() 
      {
      runCommand('npm remove '+name, doWhile0);
      });
    }

  /*------------------------------------*/
  /* Skip package if already installed. */
  /*------------------------------------*/
  else
    doWhile1();
  };

var doWhile1 = function()
  {
  /*-------------------------------------------------------*/
  /* Create link to global package from local environment. */
  /*-------------------------------------------------------*/
  if (doLinks && !fs.existsSync(path.join('node_modules', name)))
    runCommand('npm link '+name, doWhile);
  else
    doWhile();
  };

Тепер, якщо я хочу оновити глобальний інструмент для наших розробників, я оновлюю об’єкт "пакети" і перевіряю новий сценарій. Мої розробники перевіряють це і або запускають його з "вузлом npm-setup.js", або "npm install" з будь-якого з розроблених продуктів для оновлення глобального середовища. Вся справа займає 5 хвилин.

Крім того, щоб налаштувати середовище для нового розробника, вони повинні спочатку встановити лише NodeJS та GIT для Windows, перезавантажити комп’ютер, перевірити папку "Спільні файли" та будь-які продукти, що розробляються, та почати працювати.

"Package.json" для продукту .NET викликає цей сценарій перед встановленням:

{ 
"name"                    : "Books",
"description"             : "Node (npm) configuration for Books Database Web Application Tools",
"version"                 : "2.1.1",
"private"                 : true,
"scripts":
  {
  "preinstall"            : "node ../../SharedFiles/npm-setup.js links",
  "postinstall"           : "bower install"
  },
"dependencies": {}
}

Примітки

  • Зверніть увагу на те, що посилання на сценарій вимагає нахилення вперед, навіть у середовищі Windows.

  • "npm ls" видасть "npm ERR! чужорідне:" повідомлення для всіх пакетів, локально пов'язаних, тому що вони не перелічені в "package.json" "залежності".

Редагувати 29.01.16

Оновлений npm-setup.jsсценарій вище змінено таким чином:

  • "Версія" пакета в var packages- тепер значення "пакет" передається npm installв командному рядку. Це було змінено для встановлення пакунків з іншого місця, ніж зареєстроване сховище.

  • Якщо пакет уже встановлений, але він не той, який вимагається, існуючий пакет видаляється та правильний встановлений.

  • З невідомих причин npm періодично видаватиме помилку EBUSY (-4082) під час встановлення або посилання. Ця помилка знаходиться в пастці і команда повторно виконується. Помилка рідко трапляється вдруге і, здається, завжди усувається.


Це рятівник @ sthames42! Я годинами тролінгував, намагаючись зрозуміти, як саме це зробити. Чіткий, всеосяжний, загалом дивовижний. #points Питання: (a) Чому Bower знаходиться в післяінсталяційній програмі, коли вона вже є в списку пакунків? (b) Як НЕ локально пов'язати глобальні пакети? Просто не включати "посилання" в команду?
MaxRocket

@MaxRocket: Радий, що можу допомогти. Я оновив відповідь, щоб включити свій останній, який працює набагато краще. Відповіді: (a) команда 'встановити bower' запускається після 'npm install' робиться для установки компонентів Bower, перелічених у файлі bower.json, не показаному тут. Я хотів, щоб мої люди могли набрати 'npm install' і повністю налаштувати їх оточення без необхідності вводити іншу команду. (б) Так.
sthames42

Поточна версія цього сценарію тепер підтримується тут .
sthames42

6

Ви можете використовувати окремий файл, наприклад npm_globals.txt, замість package.json. Цей файл міститиме кожен модуль у новому рядку, як це,

mongoose@1.4.0
node.io@0.3.3
jquery@1.5.1
jsdom@0.2.0
cron@0.1.2

Потім у командному рядку запустіть,

< npm_globals.txt xargs npm install -g

Перевірте, чи правильно вони встановлені,

npm list -g --depth=0

Що стосується того, слід робити це чи ні, я думаю, що все залежить від випадку використання. Для більшості проектів це не потрібно; і package.jsonнабагато кращим є спільне використання цих інструментів та залежностей вашого проекту .

Але сьогодні я виявляю, що я завжди встановлюю create-react-appта інші CLI в усьому світі, коли стрибаю на новій машині. Приємно мати простий спосіб встановити глобальний інструмент та його залежності, коли версія не має великого значення.

І в наші дні, я використовую npx, НПМ пакет бігуна , замість установки пакетів в глобальному масштабі.


3

Усі модулі від package.json встановлені на ./node_modules/

Я не зміг знайти це явно зазначено, але це посилання package.json для NPM .


1

Створіть власний сценарій для встановлення глобальних залежностей. Це не займе багато. package.json досить розширюється.

const {execSync} = require('child_process');

JSON.parse(fs.readFileSync('package.json'))
     .globalDependencies.foreach(
         globaldep => execSync('npm i -g ' + globaldep)
     );

Використовуючи вищесказане, ви навіть можете зробити його вбудованим, нижче!

Подивіться попередню встановлення нижче:

{
  "name": "Project Name",
  "version": "0.1.0",
  "description": "Project Description",
  "main": "app.js",
  "scripts": {
    "preinstall": "node -e \"const {execSync} = require('child_process'); JSON.parse(fs.readFileSync('package.json')).globalDependencies.foreach(globaldep => execSync('npm i -g ' + globaldep));\"",
    "build": "your transpile/compile script",
    "start": "node app.js",
    "test": "./node_modules/.bin/mocha --reporter spec",
    "patch-release": "npm version patch && npm publish && git add . && git commit -m \"auto-commit\" && git push --follow-tags"
  },
  "dependencies": [
  },
  "globalDependencies": [
    "cordova@8.1.2",
    "ionic",
    "potato"
  ],
  "author": "author",
  "license": "MIT",
  "devDependencies": {
    "chai": "^4.2.0",
    "mocha": "^5.2.0"
  },
  "bin": {
    "app": "app.js"
  }
}

Автори вузла можуть не допустити package.json - файл проекту. Але це.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.