我可以从运行在Node.js中的javascript安装一个NPM包吗?

时间:2022-05-03 06:31:02

Can I install a NPM package from a javascript file running in Node.js? For example, I'd like to have a script, let's call it "script.js" that somehow (...using NPM or not...) install a package usually available through NPM. In this example, I'd like to install "FFI". (npm install ffi)

我可以从运行在Node.js中的javascript文件中安装一个NPM包吗?例如,我想要一个脚本,我们称之为“脚本”。js”,以某种方式(…是否使用NPM)安装一个通常通过NPM提供的包。在本例中,我想安装“FFI”。(npm安装ffi)

6 个解决方案

#1


83  

It is indeed possible to use npm programmatically, and it was outlined in older revisions of the documentation. It has since been removed from the official documentation, but still exists on source control with the following statement:

确实有可能以编程方式使用npm,在文档的旧版本中已经对其进行了概述。它已经从官方文件中删除,但仍然存在于源代码控制中,声明如下:

Although npm can be used programmatically, its API is meant for use by the CLI only, and no guarantees are made regarding its fitness for any other purpose. If you want to use npm to reliably perform some task, the safest thing to do is to invoke the desired npm command with appropriate arguments.

虽然npm可以以编程方式使用,但它的API仅供CLI使用,并且不保证它适合任何其他目的。如果希望使用npm可靠地执行某些任务,最安全的做法是使用适当的参数调用所需的npm命令。

The semantic version of npm refers to the CLI itself, rather than the underlying API. The internal API is not guaranteed to remain stable even when npm's version indicates no breaking changes have been made according to semver.

npm的语义版本指的是CLI本身,而不是底层API。即使npm的版本表明没有根据semver进行任何破坏更改,内部API也不能保证保持稳定。

In the original documentation, the following is the code sample that was provided:

在原始文件中,提供的代码示例如下:

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) { ... })
})

Since npm exists in the node_modules folder, you can use require('npm') to load it like any other module. To install a module, you will want to use npm.commands.install().

由于npm存在于node_modules文件夹中,您可以像其他模块一样使用require('npm')来加载它。要安装一个模块,您需要使用npm.commands.install()。

If you need to look in the source then it's also on GitHub. Here's a complete working example of the code, which is the equivalent of running npm install without any command-line arguments:

如果您需要查看源代码,那么它也在GitHub上。这里有一个完整的代码工作示例,相当于运行npm安装,不带任何命令行参数:

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

Note that the first argument to the install function is an array. Each element of the array is a module that npm will attempt to install.

注意,install函数的第一个参数是一个数组。数组的每个元素都是npm将要尝试安装的模块。

More advanced use can be found in the npm-cli.js file on source control.

可以在npm-cli中找到更高级的用法。源控件上的js文件。

#2


19  

yes. you can use child_process to execute a system command

是的。可以使用child_process执行系统命令

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

#3


9  

if you want to have output as well you can use:

如果你也想有输出,你可以使用:

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

this way you can watch the installation like you do it on hand and avoid bad surprises (buffer full, etc)

通过这种方式,您可以像在手边那样查看安装情况,并避免出现糟糕的意外情况(缓冲区满了,等等)

#4


6  

it can actually be a bit easy

这其实有点容易

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

#5


2  

I had a heck of a time trying to get the first example to work inside a project directory, posting here in case anyone else finds this. As far as I can tell, NPM still works fine loaded directly, but because it assumes CLI, we have to repeat ourselves a little setting it up:

我花了很长时间试图让第一个示例在一个项目目录中工作,在这里发布,以防其他人发现。就我所知,NPM仍然可以直接工作,但是由于它假设CLI,我们必须重复设置它:

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

#6


0  

I'm the author of a module that allow to do exactly what you have in mind. See live-plugin-manager.

我是一个模块的作者,这个模块允许你做你想做的事情。看到live-plugin-manager。

You can install and run virtually any package from NPM, Github or from a folder.

您可以安装并运行NPM、Github或文件夹中的任何包。

Here an example:

下面一个例子:

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

In the above code I install moment package at runtime, load and execute it. At the end I uninstall it.

在上面的代码中,我在运行时安装了moment包,加载并执行它。最后我卸载了它。

Internally I don't run npm cli but actually download packages and run inside a node VM sandbox.

在内部,我不运行npm cli,而是实际下载包并在节点VM沙箱中运行。

#1


83  

It is indeed possible to use npm programmatically, and it was outlined in older revisions of the documentation. It has since been removed from the official documentation, but still exists on source control with the following statement:

确实有可能以编程方式使用npm,在文档的旧版本中已经对其进行了概述。它已经从官方文件中删除,但仍然存在于源代码控制中,声明如下:

Although npm can be used programmatically, its API is meant for use by the CLI only, and no guarantees are made regarding its fitness for any other purpose. If you want to use npm to reliably perform some task, the safest thing to do is to invoke the desired npm command with appropriate arguments.

虽然npm可以以编程方式使用,但它的API仅供CLI使用,并且不保证它适合任何其他目的。如果希望使用npm可靠地执行某些任务,最安全的做法是使用适当的参数调用所需的npm命令。

The semantic version of npm refers to the CLI itself, rather than the underlying API. The internal API is not guaranteed to remain stable even when npm's version indicates no breaking changes have been made according to semver.

npm的语义版本指的是CLI本身,而不是底层API。即使npm的版本表明没有根据semver进行任何破坏更改,内部API也不能保证保持稳定。

In the original documentation, the following is the code sample that was provided:

在原始文件中,提供的代码示例如下:

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) { ... })
})

Since npm exists in the node_modules folder, you can use require('npm') to load it like any other module. To install a module, you will want to use npm.commands.install().

由于npm存在于node_modules文件夹中,您可以像其他模块一样使用require('npm')来加载它。要安装一个模块,您需要使用npm.commands.install()。

If you need to look in the source then it's also on GitHub. Here's a complete working example of the code, which is the equivalent of running npm install without any command-line arguments:

如果您需要查看源代码,那么它也在GitHub上。这里有一个完整的代码工作示例,相当于运行npm安装,不带任何命令行参数:

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

Note that the first argument to the install function is an array. Each element of the array is a module that npm will attempt to install.

注意,install函数的第一个参数是一个数组。数组的每个元素都是npm将要尝试安装的模块。

More advanced use can be found in the npm-cli.js file on source control.

可以在npm-cli中找到更高级的用法。源控件上的js文件。

#2


19  

yes. you can use child_process to execute a system command

是的。可以使用child_process执行系统命令

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

#3


9  

if you want to have output as well you can use:

如果你也想有输出,你可以使用:

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

this way you can watch the installation like you do it on hand and avoid bad surprises (buffer full, etc)

通过这种方式,您可以像在手边那样查看安装情况,并避免出现糟糕的意外情况(缓冲区满了,等等)

#4


6  

it can actually be a bit easy

这其实有点容易

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

#5


2  

I had a heck of a time trying to get the first example to work inside a project directory, posting here in case anyone else finds this. As far as I can tell, NPM still works fine loaded directly, but because it assumes CLI, we have to repeat ourselves a little setting it up:

我花了很长时间试图让第一个示例在一个项目目录中工作,在这里发布,以防其他人发现。就我所知,NPM仍然可以直接工作,但是由于它假设CLI,我们必须重复设置它:

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

#6


0  

I'm the author of a module that allow to do exactly what you have in mind. See live-plugin-manager.

我是一个模块的作者,这个模块允许你做你想做的事情。看到live-plugin-manager。

You can install and run virtually any package from NPM, Github or from a folder.

您可以安装并运行NPM、Github或文件夹中的任何包。

Here an example:

下面一个例子:

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

In the above code I install moment package at runtime, load and execute it. At the end I uninstall it.

在上面的代码中,我在运行时安装了moment包,加载并执行它。最后我卸载了它。

Internally I don't run npm cli but actually download packages and run inside a node VM sandbox.

在内部,我不运行npm cli,而是实际下载包并在节点VM沙箱中运行。