NodeJS вимагають глобальний модуль / пакет


160

Я намагаюся встановити глобально, а потім використовувати foreverі, forever-monitorяк це:

npm install -g forever forever-monitor

Я бачу звичайний вихід, а також операції, що копіюють файли на глобальний шлях, але тоді, якщо я спробую, require("forever");я отримую помилку, кажучи, що модуль не знайдено.

Я використовую останню версію і вузла, і npm, і я вже знаю про зміни, які npm зробив у глобальній та локальній установці, але я дійсно не хочу встановлювати localy для кожного проекту, і я працюю на платформі, яка не робить не підтримую, linkтому npm linkпісля глобальної установки для мене неможливо.

Моє запитання: чому я не можу вимагати глобально встановлений пакет? Це особливість чи помилка? Або я роблю щось не так?

PS: Просто для того, щоб було зрозуміло: я не хочу встановлювати локально.




так це ~/.config/yarn/globalдля пряжі
localhostdotdev

Відповіді:


215

У Node.js, вимога не дивиться у папку, де встановлені глобальні модулі.

Ви можете це виправити, встановивши змінну середовища NODE_PATH. У Linux це буде:

export NODE_PATH=/usr/lib/node_modules

Примітка. Це залежить від того, де фактично встановлені ваші глобальні модулі.

Див.: Завантаження із глобальних папок .


24
На моїй машині Ubuntu 13.10 глобальний шлях для модулів відрізняється від показаного тут. Мені довелося використовувати export NODE_PATH=/usr/local/lib/node_modulesзамість цього.
Дрю Ноакс

11
Якщо ви перебуваєте в Windows 7/8 і не скасували жодних із стандартних налаштувань Node, встановлення NODE_PATHзмінної середовища C:\Users\{USERNAME}\AppData\Roaming\npm\node_modules, ймовірно, спрацює.
Уес Джонсон

5
@WesJohnson Just %AppData%\npm\node_modulesбуде працювати в Windows 10.
theblang

6
Якщо я встановлю, чи NODE_PATHможу я використовувати глобальні та локальні модулі одночасно?
Пауло Олівейра

6
Або замість статичного шляху, тобто якщо ви використовуєте NVM:NODE_PATH=$(npm root -g)
holmberd

97

Після установки пакету в глобальному масштабі ви повинні зв’язати локальний проект з глобальним пакетом

npm install express -g
cd ~/mynodeproject/
npm link express  

Дивіться тут


2
Я працюю на платформі, яка не підтримує посилання (як моє запитання) blog.nodejs.org/2011/04/06/npm-1-0-link
alexandernst

1
яку платформу ви використовуєте?
користувач568109

1
Я дійсно не хочу возитися з посиланням (ні символічними посиланнями взагалі). Я просто хочу встановити пакети в усьому світі та вимагати їх. Я знаю, що NPM був перероблений, щоб уникнути цього, але наскільки важко було б досягти чогось подібного?
alexandernst

13
Що робити, якщо у мене немає проекту? Скажи ~/some-stand-alone-random-nodejs-test.js. Я не хочу перетворювати свою домашню папку в каталог проектів. Я не хочу створювати нові папки для кожного невеликого експерименту.
AnnanFay

1
Працював ідеально на Windows 8.1. З командного рядка node cd до локальної папки node_modules моїх проектів потім виконується. npm link <module>Потім ви побачите ярлик (посилання), створений у папці node_module ваших проектів, що посилається на модуль глобального вузла.
динамічнонк

26

Вибачте за некромантію, але я можу вказати жорстко закодовані шляхи до встановлених глобально модулів:

var pg = require("/usr/local/lib/node_modules/pg");

Це не ідеально, але враховуючи, що Unity3d намагається "зібрати" весь javascript, що входить до каталогу проектів, я дійсно не можу встановити жодних пакетів.


4
Unity3D не підтримує JavaScript. Він підтримує JS-подібний синтаксис для свого інтерпретатора / компілятора Boo (Boo - мова, схожа на Python для .NET), що оманливо продається як "JavaScript" . Більш точна назва мови, яку підтримує Unity, - UnityScript . Оскільки він навіть не близький до тієї ж мови, поруч із жодним JS, написаним для Інтернету чи для Node.js, не працюватиме в Unity. Набагато більше інформації про відмінності в офіційній вікі Unity: wiki.unity3d.com/index.php/UnityScript_versus_JavaScript
Slipp D. Thompson

19

Я знаю, що це старе питання, але я зіткнувся з цим, намагаючись зробити перевірку версій за semverдопомогою preinstallсценарію в package.json. Оскільки я знав, що не можу залежати від будь-яких встановлених локальних модулів, я використовував це для того, щоб вимагати semverвід глобальної node_modulesпапки (як це npmзалежить від того, я знаю, що вона є):

function requireGlobal(packageName) {
  var childProcess = require('child_process');
  var path = require('path');
  var fs = require('fs');

  var globalNodeModules = childProcess.execSync('npm root -g').toString().trim();
  var packageDir = path.join(globalNodeModules, packageName);
  if (!fs.existsSync(packageDir))
    packageDir = path.join(globalNodeModules, 'npm/node_modules', packageName); //find package required by old npm

  if (!fs.existsSync(packageDir))
    throw new Error('Cannot find global module \'' + packageName + '\'');

  var packageMeta = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json')).toString());
  var main = path.join(packageDir, packageMeta.main);

  return require(main);
}

Мені подобається такий підхід, оскільки для використання не потрібна установка будь-яких спеціальних модулів.

Я не працював з NODE_PATHрішенням, як пропонують інші, оскільки я хотів змусити це працювати на кому-небудь машині, не вимагаючи додаткової конфігурації / налаштування перед запуском npm installдля мого проекту.

Як це кодується, гарантується лише пошук модулів верхнього рівня (встановлених за допомогою npm install -g ... ) або необхідних модулів npm(перелічених dependenciesтут: https://github.com/npm/npm/blob/master/package.json ). Якщо ви використовуєте більш нову версію NPM, вона може виявити залежності інших глобально встановлених пакетів, оскільки node_modulesтепер для папок є більш плавна структура .

Сподіваюся, це комусь корисно.


19

Відповідно до документації , Node.js здійснюватиме пошук у таких місцях за замовчуванням:

  1. Шлях, вказаний у NODE_PATHзмінній оточення .

    Примітка: NODE_PATHзмінна середовище встановлюється в список абсолютних шляхів, обмежений двокрапкою.

  2. Поточна node_modulesпапка. (місцеві)

  3. $HOME/.node_modules (глобальна)

    Примітка: $HOMEце домашній каталог користувача.

  4. $HOME/.node_libraries (глобальна)
  5. $PREFIX/lib/node (глобальна)

    Примітка: $PREFIXв Node.js, налаштовані node_prefix.

    Щоб перевірити поточне значення node_prefix, запустіть:

    node -p process.config.variables.node_prefix

    Примітка: Префікс відповідає --prefixпарам під час складання і відносно process.execPath. Не плутати зі значенням npm config get prefixкоманди. джерело

Якщо даний модуль неможливо знайти, це означає, що він не присутній в одному з перерахованих вище місць.

Розташування глобальної кореневій папці , в якій встановлені модулі можуть бути роздруковані: npm root -g(за замовчуванням шлях обчислюється під час виконання , якщо не перевизначений в npmrcфайлі ).

Рішення

Ви можете спробувати наступні способи вирішення:

  • Вкажіть своє глобальне розташування модуля в NODE_PATHзмінній середовища. Напр

    echo 'require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node

    Щоб перевірити та роздрукувати значення NODE_PATH, запустіть:

    echo 'console.log(process.env.NODE_PATH); require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node 
  • Для більш постійного рішення зв’яжіть вашу $HOME/.node_modulesглобальну папку користувача, щоб вказати на кореневу папку, виконавши цю команду:

    ln -vs "$(npm root -g)" "$HOME"/.node_modules

    Потім повторно перевірити його за допомогою echo 'require("forever")' | nodeкоманди :.

  • Тимчасово змініть поточну папку на місце, де розширення встановлено глобально, перед тим, як викликати сценарій. Напр

    npm install -g forever
    cd "$(npm root -g)"
    echo 'require("forever")' | node
    cd -
  • Налаштуйте глобальне призначення установки у npmфайлі userconfig (див . :)npm help 5 npmrc або userconfigparam ( --prefix).

    Для відображення поточної конфігурації, виконайте команду: npm config list.

    Для редагування поточної конфігурації, виконайте команду: npm config edit.

  • Вказуйте повний шлях розташування модулів вузлів під час виклику require(). Напр

    require("/path/to/sub/module")
  • Встановіть пакет у спеціальне місце, наприклад,

    npm install forever -g --prefix "$HOME"/.node_modules

    Однак установка піде внизу ~/.node_modules/lib/node_modules/, тому місце все ще потрібно додати.

    Дивіться: npm-локальний пакет встановлення у власні місця

  • Створіть символьну посилання в поточній папці з місця глобального пакету. Напр

    npm link forever

Це схоже на 4. Поточна папка node_modules. (місцевий) має пріоритет понад 3. $ PREFIX / lib / node (глобальний)
Király István

Місцеві папки node_modules завжди мають пріоритет над глобальними папками!
Кіралі Іштван

14

Ви можете використовувати пакет requiregдля вирішення цієї проблеми:

var forever = require('requireg')('forever')

зробить трюк.

Також є ще один модуль, global-npmхоча специфічний лише для використання глобального npm, ви можете подивитися короткий код і побачити, як працює техніка.


цікаво, але метод NODE_PATH, мабуть, більш канонічний
Олександр Міллз

краса в NODE_PATHтому, що вам не потрібно змінювати жоден код. (мій випадок використання - це класифікація багатьох студентських проектів, де я не хочу запускатись npm installдля кожного, а також не хочу, щоб вони мали node_modulesкаталог).
амент

Ні, це не зробить трюк, тому що ви не вимагаєте requiregв першу чергу, у цьому вся суть.
thisismydesign

6

Для утиліт CLI, які залежать від великих модулів, наприклад puppeteer, я люблю нерестувати npm root -gі використовувати його, щоб вимагати глобальний модуль.

try {
  const root = require('child_process').execSync('npm root -g').toString().trim()
  var puppeteer = require(root + '/puppeteer')
} catch (err) {
  console.error(`Install puppeteer globally first with: npm install -g puppeteer`)
  process.exit(1)
}

3

Ви можете помістити цей рядок у свій .profileфайл:

export NODE_PATH = "$ (npm config отримати префікс) / lib / node_modules"

Це дозволить nodeвикористовувати глобальний шлях.


1
Ні. Це загальний спосіб отримання глобального node_modules. Це стара відповідь, але я пам’ятаю, що я отримав її десь із документації. У будь-якому випадку в моєму комп’ютері (у 2020 році) є глобальний node_modulesкаталог npm usr/lib/node_modules. У будь-якому разі, я довіряю npm config get prefixтому, що він використовується глобально npm щоразу, коли встановлено глобальний пакет, тому він повинен бути правильним.
Луїс Пауло

1
Так чи інакше (я не сказав цього в своїй початковій відповіді, тому що я не дуже досвідчений в Node.JS), використання глобально встановлених пакетів у програмі є випадком кращого використання, і це потрібно рідко робити, тому що в проекті це створить проблеми, коли проект прихильний до VCS та клонований в іншому середовищі через те, що конкретна залежність не міститься у package.jsonфайлі чи в yarn.lock/ package-lock.json.
Луїс Пауло

1
Ой! Я тепер розумію. Я вважаю, ви помиляєте NODE_PATH з PATH. PATH - це те, де оболонка шукатиме виконувані файли. NODE_PATH - це те, де вузол шукатиме пакунки. Він почнеться з перегляду поточного каталогу node_modulesпапки, потім це батьківський, потім батьківський, ... поки не знайде node_modulesпапку, яка містить цей модуль. Однак якщо ви встановите пакет у всьому світі, він не буде знаходитися у будь-якій node_modulesпапці над поточним каталогом сценарію, тому ви використовуєте NODE_PATH як резервний, де вузол шукатиме пакунки.
Луїс Пауло

1
ахахаха @ Луїс Пауло, ти абсолютно правий !! Пробач! Я спробую видалити деякі мої коментарі, щоб запобігти плутанині, приємній роботі і дякую
Ryan Taylor

@Ryan Taylor Не слід видаляти коментарі та питання, як тільки вони будуть вирішені, тому що хтось інший може мати ті самі. Зараз це просто виглядає так, що я мав монолог у коментарях! ахахах
Луїс Пауло
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.