2013-03-02 21 views
45

C'è un modo per specificare le dipendenze specifiche del sistema operativo in un file package.json NPM?npm package.json OS dipendenza specifica

Ad esempio, vorrei solo installare 'dbus' (https://npmjs.org/package/dbus) come dipendenza per il mio modulo se l'utente sta eseguendo Linux. Avrei una dipendenza diversa per Mac e Windows.

+5

Buona domanda. So che c'è il campo 'os' in [package.json] (https://npmjs.org/doc/json.html), ma questo non ti permette di scambiare dipendenze basate sulla piattaforma corrente - è solo dichiara a quali piattaforme un pacchetto è inserito nella whitelist/blacklist. Per esempio, questa struttura in 'package.json': ' "os": [ "! Win32", "Darwin"] ' significa "questo pacchetto non verrà eseguito in Windows, ma verrà eseguito su Mac".Sfortunatamente, questo non raggiunge davvero quello che stai chiedendo. – smithclay

+0

^Questo è esattamente il problema, se il modulo dbus ha binding nativi che verranno compilati solo su un sistema operativo specifico ([come menzionato di seguito nel commento] (http://stackoverflow.com/questions/15176082/npm-package-json- os-specific-dependency # comment22801812_15670089)), il suo package.json dovrebbe includere quel campo 'os'. –

risposta

25

C'è un possibile buon modo di fare questo, a seconda della configurazione.

NPM package.json supporta un os chiave,

e anche optionalDependencies

  • os può essere utilizzato per specificare quale sistema operativo di un modulo può essere installato su.
  • optionalDependencies sono dipendenze dei moduli che se non possono essere installati, NPM li ignora e continua l'installazione.

In questo modo si può avere il vostro modulo hanno una dipendenza opzionale per ciascun sistema operativo, e solo quello che funziona sarà caricato/installato^^

EDIT:. Come @Sebastien cita di seguito, questo approccio è pericoloso. Per ogni SO, almeno una delle dipendenze è "richiesta" e il resto "opzionale". Fare tutte le versioni del opzionale dipendenza significa che se l'installazione non riesce per un motivo legittimo, sarà silenziosamente ignorare l'installazione e ti verrà manca una dipendenza si ha realmente bisogno.

+2

Ho appena trovato questa risposta (dopo aver risposto al tuo commento sugli antipattern). Sembra una soluzione molto migliore rispetto all'utilizzo di uno script di installazione! Ora che so che questo è disponibile, puoi ignorare il mio commento (cercherò di eliminarlo/modificarlo se non è troppo tardi) – Metalskin

+0

Vorrei anche poter cancellare il mio commento, dato che ho finito per usare pesantemente gli script di installazione con questa soluzione>. < – TinyTimZamboni

+0

puoi mostrarmi un esempio completo? say 'fsevents' è una dipendenza opzionale su OSX che NON mi interessa perché il mio script di build è in esecuzione su LINUX. –

6

Penso che la risposta è no. Mi viene in mente un paio di soluzioni alternative anche se - il più semplice è quello di aggiungere solo che tutto package.json indipendentemente dal sistema operativo, e quindi require() quella corretta in fase di esecuzione.

Se questo non funziona per voi, si potrebbe essere in grado di utilizzare uno script di installazione per ottenere il risultato che stai per andare - https://docs.npmjs.com/misc/scripts

non ho ancora testato questo, ma penso che avrebbe funzionato:

aggiungere qualcosa di simile al tuo package.json:

,"scripts": { 
    "install": "node install_dependencies.js" 
} 

e quindi aggiungere un file di install_dependencies.js che controlla il sistema operativo ed esegue i comandi appropriati di npm install ....

+5

Il problema è che le mie dipendenze hanno associazioni native che compilano solo su un sistema operativo specifico, quindi non posso averle come dipendenze esplicite. Il tuo suggerimento per lo script di installazione di npm funziona, ho usato os.platform() per rilevare quale piattaforma l'utente sta usando; Gli script di installazione – sandeepmistry

+2

sono ora considerati un 'antipattern' [fonte] (https://www.npmjs.org/doc/misc/npm-scripts.html#note-install-scripts-are-an-antipattern). Invece dovrebbe usare un file di compilazione .gyp – TinyTimZamboni

+1

Solo un'osservazione che non mi è stata chiara con quanto sopra. Se si utilizza 'package.json' per gestire l'installazione per un progetto e la vostra non pubblicazione, usare .gyp non è la soluzione. Fai riferimento al post in basso di TinyTimZamboni, è molto più adatto per questo scenario (http://stackoverflow.com/a/26069595/1125784). – Metalskin

1

C'è anche la binding-Shyp modulo:

https://www.npmjs.com/package/bindings-shyp

modulo di supporto per il caricamento di file di .node del modulo nativo

Questo è un modulo di supporto per gli autori di Node moduli di addon nativi .js. Fondamentalmente è il "coltellino svizzero" di require() nel file .node del tuo modulo nativo.

Nel corso della cronologia degli addon nativi di Node, gli addon sono stati compilati in una varietà di luoghi diversi, a seconda dello strumento di generazione e della versione di nodo utilizzata. A peggiorare le cose, ora lo strumento di gyp build può produrre una versione di Release o Debug, ognuno dei quali è costruito in posizioni diverse.

Questo modulo controlla tutte le possibili posizioni in cui verrà creato un addon nativo e restituisce il primo che carica correttamente.

0

Citando @npm_support a:

https://twitter.com/npm_support/status/968195526989512705

2/2 Se vuoi evitare problemi di installazione relativi a dipendenze, una via è per voi di scrivere un wrapper che è richiesto come una dipendenza regolare, e per assicurarsi che abbia optionalDeps (e anche assicurarsi che il wrapper verifichi di avere tutto il necessario per funzionare).

Ma IMHO sembra più una soluzione alternativa alla risoluzione del problema per davvero.

posso capire che NPM vuole preservare la portabilità ed evitare di trattare con le specifiche della piattaforma, ma deve essere fatto comunque e secondo me fare questo in fase di esecuzione non è ottimale (specialità se uno vuole fare di ottimizzare le dimensioni del codice).

Quindi oggi non ho una soluzione ottimale da condividere ma una discussione aperta per la proposta.

Non è possibile supportare "dipendenze condizionali" in npm?

La prima cosa che mi è venuta in mente è stata aggiungere una sezione "override" che cambierà (+ aggiungi, -remove, = sostituisci) le sezioni analizzate in corso.

Ad esempio:

dependencies: { "common-stuff": "*" } overrides: { "os: { linux: { dependencies: { "+best-linux-module" } } } }

E altra opzione suggerita da uno sviluppatore lo so, potrebbe essere quella di introdurre un fornisce parola chiave, quindi più moduli potrebbe fornire una stessa semantica di quanto sarebbe soddisfatto da resolver (a la debian), ma sta generando un overhead simile.

Sto cercando un approccio generico non solo incentrato sul supporto del sistema operativo ma anche su altri tipi di pacchetto (a seconda dei motori, ad esempio).

Conosci qualche problema correlato nel tracker NPM? se non sto considerando di presentare un bug di essere monitorati a:

https://github.com/npm/npm/issues?q=dependencies+conditional

Commenti benvenuto su questa idea.

Problemi correlati