web-dev-qa-db-fra.com

Dépendances optionnelles dans npm?

J'ai une question similaire à this , mais pas tout à fait la même.

Je voudrais que l'utilisateur de mon application l'installe avec toutes les dépendances nécessaires pour la façon dont il voudrait l'utiliser. Ainsi, par exemple, s'ils souhaitent persister sur MongoDB, seules les bibliothèques liées à Mongo seront installées, mais si elles souhaitent persister sur Redis, seules les bibliothèques liées à Redis seront installées. Je ne veux pas leur faire télécharger et installer des bibliothèques qu'ils n'utiliseront pas.

Je sais que je peux le faire à des fins de développement avec devDependencies, mais cela va plus loin que cela. Comme le dit la réponse à la question ci-dessus, cela est plus étroitement lié aux profils setuptoolsextras_require De Python et leiningen de Clojure. Quelque chose comme ça dans npm? J'ai vraiment l'impression que devDependencies devrait être un profil dev d'une manière plus polyvalente de spécifier les dépendances.

26
imiric

Le module de codépendance peut être ce que vous recherchez, ou tout ce qui fait quelque chose de similaire à:

  • déclarer des dépendances facultatives dans package.json qui ne sont pas automatiquement installés par npm install, disons optionalPeerDependencies
  • une fonction de style require personnalisée qui connaît optionalPeerDependencies et fait la bonne chose, y compris lancer/avertissement lorsque rien n'est trouvé qui remplit une classe requise de modules (par exemple ni redis , ni mongo, ni mysql, etc. ne sont installés).
  • documenter l'attente que les consommateurs de ce module installent au moins 1 des modules homologues en option

Une variante serait que si la fonctionnalité de base du module fonctionne sans aucune dépendance facultative (par exemple, le modèle de plug-in), pas d'erreur/d'avertissement lorsque rien n'est trouvé qui remplit une dépendance entre pairs.

Une autre variante consiste à faire la liste ci-dessus tout en tenant compte des dépendances de production par rapport au développement, c'est-à-dire un analogue pour dependencies et devDependencies.

Peut-être combiné avec un à la demande tel que des modules optionnels sont requis paresseusement, par exemple:

exports = {
    Core : require('./core'),
    get redis(){ return require('./redis'); },
    get mongo(){ return require('./mongo'); }
}
10
toolbear

Si vous voulez de simples dépendances optionnelles comme des plugins, par ex. si vous installez foo vous l'exécuterez coloré mais s'il n'est pas installé, vous n'avez aucun problème et le voyez en gris, alors vous pouvez utiliser facultatifDépendances dans le package.json :

{
  "name": "watchit",
  "version": "1.2.3",
  "optionalDependencies": {
    "foo": "^2.0.0"
  }
}

Et dans le code:

try {
  var foo = require('foo')
  var fooVersion = require('foo/package.json').version
} catch (er) {
  foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
  foo = null
}

// .. then later in your program ..

if (foo) {
  foo.doFooThings()
}

Extrait de la documentation package.json .

10
PhoneixS

npm n'a vraiment pas été conçu pour cela, car l'une des parties les plus difficiles de la gestion des dépendances consiste à assurer des versions rapides et reproductibles, faciles et relativement sûres. Mais je crois qu'il y a un cas d'utilisation, et il y en avait certainement pour moi. J'ai donc écrit un package pour faire exactement ce que vous demandez.

Mon colis est install-subset, et peut être installé globalement avec npm install -g install-subset

https://www.npmjs.com/package/install-subset

Tout d'abord, vous créez des listes blanches et des listes noires pour les sous-ensembles d'installation nommés dans votre package.json comme ceci:

"subsets": {
    "build": {
        "whitelist": [
            "babel-cli",
            "dotenv"
        ]
    },
    "test": {
        "blacklist": [
            "eslint",
            "lint-rules",
            "prettier"
        ]
    }
}

Appelez-le ensuite avec, par exemple, install-subset test

Cela réécrira temporairement votre package.json pour ne pas installer ces packages sur liste noire, puis le restaurera, ce qui, selon les packages, peut économiser beaucoup de temps et de bande passante.

Fonctionne également avec le fil, est open source et les problèmes/relations publiques sont les bienvenus.

Dans de nombreux cas, j'utilise cela sur notre serveur ci pour réduire le temps de construction, et sur notre dernier React projet natif, a pris notre nouvelle installation de développeur typique de 72 secondes à environ 20 secondes.

2
tabrindle

Ce que je fais, c'est configurer un script d'installation dans mon package.json, à l'intérieur de scripts, comme ceci:

"install": "node ./my-tools/my-install.js",

Il s'exécutera juste après npm install se termine. Je l'utilise principalement pour générer automatiquement un .env fichier avec valeurs par défaut.

Le my-install.js le script pourrait exécuter différentes commandes, créer des fichiers, demander une entrée utilisateur, donc là vous pourriez dire "Vous voulez Redis ou Mongo?":

const exec = require('child_process').exec;
const readline = require('readline');

// Insert "Ask question script" here
// using readline core module

if ( option == 'mongo' )
  exec('npm install mongoose');

if ( option == 'redis' )
  exec('npm install redis');

Ceci est une réponse très rapide, consultez readline pour lire correctement les entrées utilisateur et processus enfant pour exécuter les commandes et traiter la sortie, etc.

Notez également que le script d'installation peut être celui que vous souhaitez (python, bash, etc.)

1
aesede