Memang mungkin untuk menggunakan npm secara terprogram, dan itu diuraikan dalam revisi dokumentasi yang lebih lama. Sejak itu telah dihapus dari dokumentasi resmi, tetapi masih ada di kontrol sumber dengan pernyataan berikut:
Meskipun npm dapat digunakan secara terprogram, API-nya dimaksudkan untuk digunakan hanya oleh CLI, dan tidak ada jaminan yang dibuat terkait kesesuaiannya untuk tujuan lain apa pun. Jika Anda ingin menggunakan npm untuk melakukan beberapa tugas dengan andal, hal teraman yang harus dilakukan adalah menjalankan perintah npm yang diinginkan dengan argumen yang sesuai.
Versi semantik npm mengacu pada CLI itu sendiri, bukan API yang mendasarinya. API internal tidak dijamin akan tetap stabil meskipun versi npm menunjukkan tidak ada perubahan yang melanggar yang telah dibuat menurut semver .
Dalam dokumentasi asli, berikut ini adalah contoh kode yang diberikan:
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)
})
npm.registry.log.on('log', function (message) { ... })
})
Karena npm ada di node_modules
folder, Anda dapat menggunakannya require('npm')
untuk memuatnya seperti modul lainnya. Untuk memasang modul, Anda akan ingin menggunakan npm.commands.install()
.
Jika Anda perlu melihat sumbernya maka itu juga ada di GitHub . Berikut adalah contoh lengkap kode yang berfungsi, yang setara dengan menjalankan npm install
tanpa argumen baris perintah apa pun:
var npm = require('npm');
npm.load(function(err) {
npm.commands.install(['ffi'], function(er, data) {
});
npm.on('log', function(message) {
console.log(message);
});
});
Perhatikan bahwa argumen pertama untuk fungsi instal adalah array. Setiap elemen dari array adalah modul yang akan coba dipasang oleh npm .
Penggunaan lebih lanjut dapat ditemukan di npm-cli.js
file pada kontrol sumber.
npm install npm --save
terlebih dahulu. Contoh bekerja dengan baik :)npm
memiliki banyak dependensi, jadi menambahkannya ke modul Anda kemungkinan besar akan mengakibatkan proses download JAUH lebih lama. Lihat salah satuchild_process
jawaban untuk memanfaatkan npm global yang sudah terinstal di mesin pengguna Anda.npm.config
untuknpm.load
! Bahkan @isaacs tidak tahu hal aneh seperti apa yang akan terjadi nanti! Lihat github.com/npm/npm/issues/4861#issuecomment-40533836 Alih-alih, Anda dapat melewati argumen pertama.process.cwd()
)npm install npm --save
Anda dapat menggunakan child_process . exec atau execSync untuk menelurkan shell kemudian menjalankan perintah yang diinginkan di dalam shell itu, melakukan buffering pada setiap output yang dihasilkan:
var child_process = require('child_process'); child_process.execSync('npm install ffi',{stdio:[0,1,2]});
Jika fungsi callback disediakan, itu dipanggil dengan argumen (error, stdout, stderr). Dengan cara ini Anda dapat menjalankan instalasi seperti Anda melakukannya secara manual dan melihat output lengkapnya.
Metode child_process.execSync () umumnya identik dengan child_process.exec () dengan pengecualian bahwa metode tersebut tidak akan kembali sampai proses anak ditutup sepenuhnya.
sumber
stdio: [0,1,2]
dilakukannya?Iya. Anda dapat menggunakan child_process untuk menjalankan perintah sistem
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); } });
sumber
npm.cmd
sebagai gantinya.sebenarnya bisa sedikit mudah
var exec = require('child_process').exec; child = exec('npm install ffi').stderr.pipe(process.stderr);
sumber
Saya sempat mencoba mendapatkan contoh pertama untuk bekerja di dalam direktori proyek, memposting di sini jika ada orang lain yang menemukan ini. Sejauh yang saya tahu, NPM masih berfungsi dengan baik saat dimuat secara langsung, tetapi karena mengasumsikan CLI, kami harus mengulangi sedikit pengaturannya:
// 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); }); });
sumber
pacote adalah paket yang digunakan npm untuk mengambil metadata paket dan tarball. Ini memiliki API publik yang stabil.
sumber
Saya penulis modul yang memungkinkan untuk melakukan apa yang Anda pikirkan. Lihat live-plugin-manager .
Anda dapat menginstal dan menjalankan hampir semua paket dari NPM, Github atau dari folder.
Berikut contohnya:
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();
Dalam kode di atas saya menginstal
moment
paket saat runtime, memuat dan menjalankannya. Pada akhirnya saya mencopotnya.Secara internal saya tidak menjalankan
npm
cli tetapi sebenarnya mengunduh paket dan berjalan di dalam kotak pasir VM node.sumber
Sebuah solusi hebat dari @hexacyanide, tetapi ternyata NPM tidak lagi mengeluarkan peristiwa "log" (setidaknya pada versi 6.4.1). Sebaliknya, mereka mengandalkan modul mandiri https://github.com/npm/npmlog . Untungnya ini tunggal, jadi kita bisa mencapai contoh yang sama yang digunakan NPM untuk log dan berlangganan kejadian log:
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" ); }); });
Seperti yang Anda lihat dari kode, NPM juga memancarkan metrik kinerja
process
, jadi kami juga dapat menggunakannya untuk memantau kemajuan.sumber
Opsi lain, yang tidak disebutkan di sini, adalah melakukan fork dan menjalankan CLI langsung dari
./node_modules/npm/bin/npm-cli.js
Misalnya Anda ingin dapat menginstal modul node dari menjalankan skrip pada mesin, yang tidak memiliki NPM yang diinstal. Dan Anda ingin melakukannya dengan CLI. Dalam hal ini, instal NPM di node_modules Anda secara lokal saat membangun program Anda (
npm i npm
).Kemudian gunakan seperti ini:
// 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}`); });
Kemudian program Anda bahkan bisa dikemas ke file biner, misalnya dengan paket PKG . Dalam hal ini Anda perlu menggunakan
--ignore-scripts
opsi npm, karena node-gyp diperlukan untuk menjalankan skrip prainstalsumber