web-dev-qa-db-fra.com

NodeJS nécessite un module / package global

J'essaie d'installer globalement puis d'utiliser forever et forever-monitor Comme ceci:

npm install -g forever forever-monitor

Je vois la sortie habituelle ainsi que les opérations qui copient les fichiers dans le chemin global, mais si j'essaie de require("forever");, j'obtiens une erreur indiquant que le module n'a pas été trouvé.

J'utilise la dernière version de node et de npm et je connais déjà le changement que npm a apporté lors de l'installation globale par rapport à l'installation locale, mais je je ne veux vraiment pas à installer localement sur chaque projet et je m travaillant sur une plate-forme qui ne supporte pas link donc npm link après une installation globale ne m'est pas possible.

Ma question est: pourquoi je ne peux pas exiger un paquet installé globalement? Est-ce une fonctionnalité ou un bug? Ou est-ce que je fais quelque chose de mal?

PS: Juste pour être clair: je ne veux pas installer localement.

128
alexandernst

Dans Node.js, require ne recherche pas dans le dossier où sont installés les modules globaux.

Vous pouvez résoudre ce problème en définissant la variable d'environnement NODE_PATH. Sous Linux, ce sera:

export NODE_PATH=/usr/lib/node_modules

Remarque: Cela dépend de l'endroit où vos modules globaux sont réellement installés.

Voir: Chargement depuis les dossiers globaux .

185
Daniel Uzunu

Après avoir installé le paquet globalement, vous devez lier le projet local au paquet global.

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

Voir ici

89
user568109

Toutes mes excuses pour la nécromancie, mais je suis en mesure de spécifier des chemins codés en dur vers des modules installés globalement:

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

Ce n'est pas parfait, mais étant donné qu'Unity3d essaie de "compiler" tout le javascript inclus dans le répertoire du projet, je ne peux vraiment installer aucun paquet.

23
Thomas Ingham

Je sais que c’est une vieille question, mais j’ai rencontré ce problème en essayant de vérifier certaines versions en utilisant semver dans un script preinstall dans package.json. Puisque je savais que je ne pouvais pas dépendre de modules locaux installés, je l’utilisais pour demander à semver de figurer dans le dossier global node_modules (Car npm en dépend, je sais que c’est là. ):

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);
}

J'aime cette approche car elle ne nécessite pas l'installation de modules spéciaux pour pouvoir être utilisée.

Je ne suis pas allé avec une solution NODE_PATH Comme l'ont suggéré d'autres, car je voulais que cela fonctionne sur la machine de quiconque, sans avoir à demander une configuration supplémentaire avant d'exécuter npm install Pour mon projet.

De la manière dont cela est codé, il est uniquement garanti de trouver les modules de niveau supérieur (installés à l’aide de npm install -g ...) Ou requis par npm (listés sous la forme dependencies ici: https://github.com/npm/npm/blob/master/package.json ). Si vous utilisez une version plus récente de NPM, il peut trouver des dépendances d'autres packages installés globalement car il existe actuellement une structure plus plate pour les dossiers node_modules.

J'espère que cela est utile à quelqu'un.

18
Joe Skeen

Vous pouvez utiliser le paquet requireg pour résoudre ce problème:

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

fera l'affaire.

En outre, il y a un autre module, global-npm , bien que spécifique à l’utilisation de la méthode globale npm, vous pouvez consulter le code abrégé et voir comment la technique fonctionne.

15
JP Richardson

Selon documentation , Node.js recherchera par défaut dans les emplacements suivants:

  1. Chemin spécifié dans la variable d'environnement NODE_PATH.

    Remarque: La variable d'environnement NODE_PATH Est définie sur une liste de chemins absolus délimités par des deux-points.

  2. Dossier actuel node_modules. (local)

  3. $HOME/.node_modules (global)

    Remarque: $HOME Est le répertoire de base de l'utilisateur.

  4. $HOME/.node_libraries (global)
  5. $PREFIX/lib/node (global)

    Remarque: $PREFIX Est le fichier node_prefix Configuré par Node.js.

    Pour vérifier la valeur actuelle de node_prefix, Exécutez:

    node -p process.config.variables.node_prefix
    

    Remarque: Le préfixe correspond au paramètre --prefix Pendant la construction et il est relatif à process.execPath. Ne pas confondre avec la valeur de la commande npm config get prefix.source

Si le module donné est introuvable, cela signifie qu'il n'est pas présent dans l'un des emplacements ci-dessus.

L'emplacement du dossier racine global où les modules sont installés peut être imprimé avec: npm root -g (Par défaut, le chemin est calculé au moment de l'exécution, sauf substitution dans npmrc fichier ).

Solution

Vous pouvez essayer les solutions suivantes:

  • Spécifiez l'emplacement de votre module global dans la variable d'environnement NODE_PATH. Par exemple.

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

    Pour tester et imprimer la valeur de NODE_PATH, Exécutez:

    echo 'console.log(process.env.NODE_PATH); require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node 
    
  • Pour une solution plus permanente, liez votre dossier utilisateur global $HOME/.node_modules Pour qu'il pointe vers le dossier racine, en exécutant la commande suivante:

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

    Puis re-testez-le avec la commande: echo 'require("forever")' | node.

  • Temporairement, modifiez le dossier actuel en fonction de l'emplacement d'installation de l'extension, avant d'appeler le script. Par exemple.

    npm install -g forever
    cd "$(npm root -g)"
    echo 'require("forever")' | node
    cd -
    
  • Configurez la destination d'installation globale dans npmfichier de configuration (voir: npm help 5 npmrc) Ou par userconfig param (--prefix).

    Pour afficher la configuration actuelle, exécutez: npm config list.

    Pour éditer la configuration actuelle, lancez: npm config edit.

  • Spécifiez le chemin complet de emplacement des modules de noeud lors de l'appel de require(). Par exemple.

    require("/path/to/sub/module")
    
  • Installez le package dans un emplacement personnalisé, par exemple.

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

    Cependant, l'installation ira sous ~/.node_modules/lib/node_modules/, Il faut donc ajouter l'emplacement.

    Voir: package d'installation local npm à l'emplacement personnalisé

  • Créer un lien symbolique dans le dossier actuel à partir de l'emplacement du paquet global. Par exemple.

    npm link forever
    
14
kenorb

Pour les utilitaires CLI qui dépendent de gros modules, comme puppeteer, j’aime créer un npm root -g et utilisez-le pour demander le module global.

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)
}
2
Christophe Marois

Vous pouvez mettre cette ligne dans votre .profile fichier:

export NODE_PATH = "$ (préfixe d'obtention de la configuration npm)/lib/node_modules"

Ceci fera que node utilise le chemin global.

0
Luis Paulo