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

Jus*_*tin 82 javascript node.js npm

我可以从Node.js中运行的javascript文件安装NPM包吗?例如,我想要一个脚本,让我们称它为"script.js",不知何故(......使用NPM或不...)安装一个通常可以通过NPM获得的包.在这个例子中,我想安装"FFI".(npm install ffi)

hex*_*ide 103

确实可以以编程方式使用npm,并且在文档的旧版本中对其进行了概述.它已从官方文档中删除,但仍然存在于源代码管理中,并带有以下声明:

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

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

在原始文档中,以下是提供的代码示例:

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) { ... })
})
Run Code Online (Sandbox Code Playgroud)

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

如果您需要查看源代码,那么它也在GitHub上.这是代码的完整工作示例,相当于在npm install没有任何命令行参数的情况下运行:

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);
  });
});
Run Code Online (Sandbox Code Playgroud)

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

可以npm-cli.js在源代码管理的文件中找到更高级的用法.

  • 另外,要注意 - "npm"有很多依赖项,因此将它添加到模块中很可能会导致下载时间更长.查看一个`child_process`答案,以利用用户计算机上已安装的全局npm. (5认同)
  • 如果这有助于任何人 - 确保你首先安装npm --save`.示例效果很好:) (4认同)
  • 如何设置目标路径?(当 `process.cwd()` 不同时) (2认同)

The*_*ain 23

是.您可以使用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);
     }
 });
Run Code Online (Sandbox Code Playgroud)

  • 在Windows上这不起作用!你必须改为调用`npm.cmd`. (5认同)
  • 是的,你可以,但是一些依赖项将无法安装(从经验谈起,因为曾几何时我实际上为node.js写了一个[CI](https://github.com/matejkramny/node-ci)服务器) (2认同)

kra*_*uba 21

如果你想要输出你可以使用:

var child_process = require('child_process');
child_process.execSync('npm install ffi',{stdio:[0,1,2]});
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以像手头一样观看安装,避免出现意外情况(缓冲区已满等)

  • 这是所有答案中唯一的选项,例如,它可以让您运行 npm install 并获得完整的输出,就像您手动执行命令一样!谢谢你! (3认同)
  • `stdio: [0,1,2]` 的作用是什么? (2认同)

小智 9

它实际上可能有点容易

var exec = require('child_process').exec;
child = exec('npm install ffi').stderr.pipe(process.stderr);
Run Code Online (Sandbox Code Playgroud)

  • 这还有一个优点,即 stderr(和 stdout)在发生时打印,而不是在执行结束时打印! (2认同)

Meg*_*ind 5

我花了很长时间试图使第一个示例在项目目录中运行,以防其他人发现。据我所知,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);
    });
});
Run Code Online (Sandbox Code Playgroud)