webentwicklung-frage-antwort-db.com.de

Kann ich ein NPM-Paket von Javascript installieren, das in Node.js ausgeführt wird?

Kann ich ein NPM-Paket von einer in Node.js ausgeführten Javascript-Datei installieren? Zum Beispiel würde ich gerne ein Skript haben, nennen wir es "script.js", das irgendwie (... mit NPM oder nicht ...) ein normalerweise von NPM verfügbares Paket installiert. In diesem Beispiel möchte ich "FFI" installieren. (npm install ffi) 

68
Justin

Es ist in der Tat möglich, npm programmgesteuert zu verwenden, was in älteren Versionen der Dokumentation beschrieben wurde. Es wurde seitdem aus der offiziellen Dokumentation entfernt, ist jedoch in der Quellcodeverwaltung mit der folgenden Anweisung vorhanden:

Obwohl npm programmgesteuert verwendet werden kann, ist seine API für die Verwendung durch .__ gedacht. nur die CLI, und es wird keine Garantie hinsichtlich der Eignung für eine beliebige .__ gegeben. anderer Zweck. Wenn Sie npm verwenden möchten, um eine Aufgabe zuverlässig auszuführen, Am sichersten ist es, den gewünschten npm-Befehl mit .__ aufzurufen. geeignete Argumente.

Die semantische Version von npm bezieht sich auf die CLI selbst und nicht auf die zugrunde liegende API. Es kann nicht garantiert werden, dass die interne API stabil bleibt Auch wenn die Version von npm angibt, dass keine Änderungen vorgenommen wurden nach semver.

In der Originaldokumentation ist das folgende Codebeispiel enthalten:

var npm = require('npm')
npm.load(myConfigObject, function (er) {
  if (er) return handlError(er)
  npm.commands.install(['some', 'args'], function (er, data) {
    if (er) return commandFailed(er)
    // command succeeded, and data might have some info
  })
  npm.registry.log.on('log', function (message) { ... })
})

Da npm im Ordner node_modules vorhanden ist, können Sie require('npm') wie jedes andere Modul laden. Um ein Modul zu installieren, verwenden Sie npm.commands.install().

Wenn Sie in der Quelle nachschauen müssen, ist es auch auf GitHub . Hier ist ein vollständiges Arbeitsbeispiel für den Code, der dem Ausführen von npm install ohne Befehlszeilenargumente entspricht:

var npm = require('npm');
npm.load(function(err) {
  // handle errors

  // install module ffi
  npm.commands.install(['ffi'], function(er, data) {
    // log errors or data
  });

  npm.on('log', function(message) {
    // log installation progress
    console.log(message);
  });
});

Beachten Sie, dass das erste Argument der Installationsfunktion ein Array ist. Jedes Element des Arrays ist ein Modul, das npm zu installieren versucht.

Eine weitergehende Verwendung kann in der Datei npm-cli.js in der Quellcodeverwaltung gefunden werden.

94
hexacyanide

ja. Sie können child_process verwenden, um einen Systembefehl auszuführen

var exec = require('child_process').exec,
    child;

 child = exec('npm install ffi',
 function (error, stdout, stderr) {
     console.log('stdout: ' + stdout);
     console.log('stderr: ' + stderr);
     if (error !== null) {
          console.log('exec error: ' + error);
     }
 });
20
TheBrain

wenn Sie auch Ausgabe wünschen, können Sie Folgendes verwenden:

var child_process = require('child_process');
child_process.execSync("npm install ffi",{stdio:[0,1,2]});

auf diese Weise können Sie die Installation so ansehen, wie Sie es gerade tun, und schlechte Überraschungen vermeiden (Puffer voll, usw.).

12
krankuba

es kann eigentlich ein bisschen einfach sein

var exec = require('child_process').exec;
child = exec('npm install ffi').stderr.pipe(process.stderr);
8

Ich hatte eine verdammte Zeit, als ich versuchte, das erste Beispiel für die Arbeit in einem Projektverzeichnis zu erhalten, und hier posten, falls jemand anderes dies findet. Soweit ich das beurteilen kann, funktioniert NPM immer noch gut geladen, aber da es eine CLI voraussetzt, müssen wir uns noch ein wenig aufstellen:

// this must come before load to set your project directory
var previous = process.cwd();
process.chdir(project);

// this is the part missing from the example above
var conf = {'bin-links': false, verbose: true, prefix: project}

// this is all mostly the same

var cli = require('npm');
cli.load(conf, (err) => {
    // handle errors
    if(err) {
        return reject(err);
    }

    // install module
    cli.commands.install(['ffi'], (er, data) => {
        process.chdir(previous);
        if(err) {
            reject(err);
        }
        // log errors or data
        resolve(data);
    });

    cli.on('log', (message) => {
        // log installation progress
        console.log(message);
    });
});
3
Megamind

Ich bin der Autor eines Moduls, mit dem Sie genau das tun können, was Sie im Sinn haben ... /. Siehe live-plugin-manager .

Sie können praktisch jedes Paket von NPM, Github oder aus einem Ordner installieren und ausführen.

Hier ein Beispiel:

import {PluginManager} from "live-plugin-manager";

const manager = new PluginManager();

async function run() {
  await manager.install("moment");

  const moment = manager.require("moment");
  console.log(moment().format());

  await manager.uninstall("moment");
}

run();

Im obigen Code installiere ich moment zur Laufzeit, lade und führe es aus. Am Ende deinstalliere ich es.

Intern führe ich nicht npm cli aus, sondern lade tatsächlich Pakete herunter und laufe in einer Node VM - Sandbox.

1
Davide Icardi

pacote ist das Paket, mit dem npm Paketmetadaten und Tarballs abruft. Es verfügt über eine stabile, öffentliche API.

0
James A. Rosen

Eine großartige Lösung von @hexacyanide, aber es stellte sich heraus, dass NPM kein "Log" -Ereignis mehr auslöst (zumindest ab Version 6.4.1). Stattdessen verlassen sie sich auf ein eigenständiges Modul https://github.com/npm/npmlog . Glücklicherweise handelt es sich um ein Singleton, sodass wir dieselbe Instanz erreichen können, die auch von NPM für Protokolle verwendet wird, und für Protokollereignisse abonnieren:

const npmlog = require( "npm/node_modules/npmlog" ),
      npm = require( "npm" );

npmlog.on( "log", msg => {
   console.log({ msg });
});

 process.on("time", milestone => {
   console.log({ milestone });
 });

 process.on("timeEnd", milestone => {
   console.log({ milestone });    
 });

 npm.load({
    loaded: false,
    progress: false,
    "no-audit": true
  }, ( err ) => {

 npm.commands.install( installDirectory, [
      "[email protected]^5.2.0",
      "[email protected]^0.8.2"
    ], ( err, data ) => {
       console.log( "done" );    
    });

  });

Wie Sie dem Code entnehmen können, gibt NPM auch Performance-Metriken für die Variable process aus, sodass wir den Fortschritt auch überwachen können.

0
Dmitry Sheiko