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) { ... })
})
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);
});
});
설치 함수의 첫 번째 인수는 배열입니다. 배열의 각 요소는 npm 이 설치를 시도 하는 모듈입니다 .
보다 고급 사용은 npm-cli.js
소스 제어 에 대한 파일에서 찾을 수 있습니다 .
npm
많은 종속성이 있으므로 모듈에 추가하면 다운로드하는 데 훨씬 더 오래 걸릴 수 있습니다. child_process
사용자 컴퓨터에 이미 설치된 글로벌 npm을 활용 하려면 답변 중 하나를 확인하십시오 .
npm.config
에 npm.load
! @isaacs조차도 어떤 종류의 이상한 일이 일어날 지 모릅니다! github.com/npm/npm/issues/4861#issuecomment-40533836을 참조하십시오 . 대신 첫 번째 인수를 건너 뛸 수 있습니다.
process.cwd()
)
npm install npm --save
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 ()와 동일합니다.
stdio: [0,1,2]
합니까?
예. 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);
}
});
npm.cmd
대신 전화해야 합니다.
실제로 조금 쉬울 수 있습니다.
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);
});
});
나는 당신이 생각하고있는 것을 정확하게 할 수있는 모듈의 저자입니다. 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
에서 런타임에 패키지를 설치 하고로드하고 실행합니다. 결국 나는 그것을 제거합니다.
내부적으로 저는 npm
cli를 실행하지 않고 실제로 패키지를 다운로드하고 노드 VM 샌드 박스 내에서 실행합니다.
@hexacyanide의 훌륭한 솔루션이지만 NPM은 더 이상 "로그"이벤트를 생성하지 않습니다 (적어도 버전 6.4.1부터). 대신 그들은 독립형 모듈 https://github.com/npm/npmlog 에 의존합니다 . 다행히 싱글 톤이므로 NPM이 로그에 사용하는 것과 동일한 인스턴스에 도달하고 로그 이벤트를 구독 할 수 있습니다.
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, [
"cross-env@^5.2.0",
"shelljs@^0.8.2"
], ( err, data ) => {
console.log( "done" );
});
});
코드에서 볼 수 있듯이 NPM은에서 성능 메트릭도 내보내 process
므로 진행 상황을 모니터링하는 데 사용할 수도 있습니다.
여기에 언급되지 않은 또 다른 옵션은 포크를 수행하고 CLI를 ./node_modules/npm/bin/npm-cli.js
예를 들어 NPM이 설치되지 않은 컴퓨터에서 스크립트를 실행하여 노드 모듈을 설치할 수 있기를 원합니다. 그리고 당신은 CLI로 그것을하고 싶습니다. 이 경우 프로그램을 빌드하는 동안 로컬 node_modules에 NPM을 설치하십시오 ( npm i npm
).
그런 다음 다음과 같이 사용하십시오.
// Require child_process module
const { fork } = require('child_process');
// Working directory for subprocess of installer
const cwd = './path-where-to-run-npm-command';
// CLI path FROM cwd path! Pay attention
// here - path should be FROM your cwd directory
// to your locally installed npm module
const cli = '../node_modules/npm/bin/npm-cli.js';
// NPM arguments to run with
// If your working directory already contains
// package.json file, then just install it!
const args = ['install']; // Or, i.e ['audit', 'fix']
// Run installer
const installer = fork(cli, args, {
silent: true,
cwd: cwd
});
// Monitor your installer STDOUT and STDERR
installer.stdout.on('data', (data) => {
console.log(data);
});
installer.stderr.on('data', (data) => {
console.log(data);
});
// Do something on installer exit
installer.on('exit', (code) => {
console.log(`Installer process finished with code ${code}`);
});
그런 다음 프로그램을 PKG 패키지 와 같이 바이너리 파일로 압축 할 수도 있습니다 . 이 경우에는 --ignore-scripts
사전 설치 스크립트를 실행하기 위해 node-gyp이 필요하기 때문에 npm 옵션 을 사용해야 합니다.
npm install npm --save
먼저 확인하십시오 . 예 훌륭한 :) 작동