[javascript] Node.js에서 실행되는 javascript에서 NPM 패키지를 설치할 수 있습니까?

Node.js에서 실행되는 javascript 파일에서 NPM 패키지를 설치할 수 있습니까? 예를 들어, 스크립트를 갖고 싶습니다. “script.js”라고 부르면 어떻게 든 (… NPM 사용 여부 …) 일반적으로 NPM을 통해 제공되는 패키지를 설치합니다. 이 예에서는 “FFI”를 설치하고 싶습니다. (npm 설치 ffi)



답변

실제로 npm을 프로그래밍 방식 으로 사용할 수 있으며 이전 버전의 설명서에 설명되어 있습니다. 이후 공식 문서에서 제거되었지만 다음과 같은 내용으로 소스 제어에 여전히 존재합니다.

npm은 프로그래밍 방식으로 사용할 수 있지만 API는 CLI에서만 사용할 수 있으며 다른 목적에 대한 적합성에 대한 보장은 없습니다. npm을 사용하여 일부 작업을 안정적으로 수행하려면 가장 안전한 방법은 적절한 인수를 사용하여 원하는 npm 명령을 호출하는 것입니다.

npm의 시맨틱 버전은 기본 API가 아닌 CLI 자체를 참조합니다. 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) { ... })
})

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

설치 함수의 첫 번째 인수는 배열입니다. 배열의 각 요소는 npm 이 설치를 시도 하는 모듈입니다 .

보다 고급 사용은 npm-cli.js소스 제어 에 대한 파일에서 찾을 수 있습니다 .


답변

child_process 를 사용할 수 있습니다 . exec 또는 execSync 를 사용하여 쉘을 생성 한 다음 해당 쉘 내에서 원하는 명령을 실행하여 생성 된 출력을 버퍼링합니다.

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

콜백 함수가 제공되면 인수 (error, stdout, stderr)와 함께 호출됩니다. 이렇게하면 수동으로 수행하는 것처럼 설치를 실행하고 전체 출력을 볼 수 있습니다.

child_process.execSync () 메서드는 자식 프로세스가 완전히 닫힐 때까지 메서드가 반환되지 않는다는 점을 제외하면 일반적으로 child_process.exec ()와 동일합니다.


답변

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


답변

실제로 조금 쉬울 수 있습니다.

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


답변

다른 사람이 이것을 발견 할 경우를 대비하여 여기에 게시하여 프로젝트 디렉토리 내에서 작업 할 첫 번째 예제를 얻으려고 노력했습니다. 내가 알 수있는 한, 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);
    });
});


답변

pacote 는 npm이 패키지 메타 데이터와 타르볼을 가져 오는 데 사용하는 패키지입니다. 안정적인 공개 API가 있습니다.


답변

나는 당신이 생각하고있는 것을 정확하게 할 수있는 모듈의 저자입니다. live-plugin-manager를 참조하십시오 .

NPM, Github 또는 폴더에서 거의 모든 패키지를 설치하고 실행할 수 있습니다.

다음은 예입니다.

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

위의 코드 moment에서 런타임에 패키지를 설치 하고로드하고 실행합니다. 결국 나는 그것을 제거합니다.

내부적으로 저는 npmcli를 실행하지 않고 실제로 패키지를 다운로드하고 노드 VM 샌드 박스 내에서 실행합니다.