Ketergantungan opsional dalam npm?

23

Saya punya pertanyaan serupa dengan ini , tetapi tidak persis sama.

Saya ingin agar pengguna aplikasi saya menginstalnya dengan dependensi apa pun yang diperlukan untuk cara dia ingin menggunakannya. Jadi, misalnya, jika mereka ingin tetap menggunakan MongoDB, maka hanya perpustakaan yang berhubungan dengan Mongo yang akan diinstal, tetapi jika mereka ingin tetap menggunakan Redis, maka hanya perpustakaan yang terkait dengan Redis yang akan diinstal. Saya tidak ingin membuat mereka mengunduh dan menginstal perpustakaan yang tidak akan mereka gunakan.

Saya tahu saya bisa melakukan itu untuk tujuan pengembangan devDependencies, tetapi ini lebih jauh dari itu. Seperti jawaban dalam pertanyaan di atas, ini lebih terkait dengan profil Python setuptools extras_requiredan Clojure leiningen. Ada yang seperti itu di npm? Saya benar-benar merasa devDependenciesharus menjadi devprofil cara yang lebih fleksibel untuk menentukan dependensi.

imiric
sumber
Hanya pemikiran tetapi Anda bisa pergi dengan beberapa paket. MyPackage-Core MyPackage-Db-Mongo MyPackage-Db-Redisdll ... banyak cara orang melakukan modul bower yang dimaksudkan untuk memperpanjang sudut .
Mike
@ Mike: Hmm terima kasih, saya akan mempertimbangkannya. Saya masih berpikir ini adalah keterbatasan package.jsonyang telah diselesaikan di manajer paket lain.
imiric
1
Ini adalah pertanyaan yang bagus, tapi saya pikir itu di luar topik karena ini tentang menggunakan beberapa alat. Pertanyaan semacam itu hanya pada topik jika mencakup bagaimana alat terintegrasi ke dalam beberapa proses pengembangan - setelah semua, situs ini adalah tentang Rekayasa Perangkat Lunak. Lihat pusat bantuan kami untuk detailnya. Harap baca: Di mana pertanyaan alat saya pergi? Penggunaan alat pengembangan seperti NPM akan menjadi topik pada Stack Overflow.
amon

Jawaban:

9

The Modul codependency mungkin apa yang Anda cari, atau apa pun yang melakukan sesuatu yang mirip dengan:

  • mendeklarasikan dependensi opsional package.jsonyang tidak diinstal secara otomatis oleh npm install, katakanlahoptionalPeerDependencies
  • requirefungsi gaya- kustom yang mengetahui optionalPeerDependenciesdan melakukan hal yang benar, termasuk melempar / memperingatkan ketika tidak ada yang memenuhi kelas modul yang diperlukan (mis. tidak redis, atau mongo, atau mysql, dll. dipasang).
  • mendokumentasikan harapan bahwa konsumen dari modul ini menginstal setidaknya 1 dari modul peer opsional

Salah satu variasi adalah jika fungsionalitas inti modul bekerja tanpa dependensi opsional (misalnya pola plugin), tidak ada kesalahan / peringatan ketika tidak ada yang ditemukan yang memenuhi dependensi rekan.

Variasi lain adalah melakukan daftar di atas sambil menghitung ketergantungan produksi versus pengembangan, yaitu analog untuk dependenciesdan devDependencies.

Mungkin dikombinasikan dengan permintaan sesuai permintaan sehingga modul opsional diperlukan dengan malas, misalnya:

exports = {
    Core : require('./core'),
    get redis(){ return require('./redis'); },
    get mongo(){ return require('./mongo'); }
}
toolbear
sumber
Saya belum membutuhkan ini untuk sementara waktu, tetapi saya pikir itu memecahkan masalah yang saya miliki. Terima kasih!
imiric
2
Ya saya pikir itu menjadi bulan Anda mungkin sudah tahu atau pindah. Saya menemukan pertanyaan Anda saat mencari jawaban sendiri jadi ini sebagian besar untuk anak cucu. Lebih dari sekali saya mencari, hanya untuk menemukan jawaban dari diri saya sendiri yang ditulis beberapa tahun sebelumnya. Jadi pertimbangkan kepentingan pribadi yang tercerahkan ini. Juga, perbarui jawaban untuk menjelaskan secara umum apa yang codependencydisediakan modul jika modul menguap dari NPM dan karena tautan tanpa kutipan adalah bentuk SO yang buruk.
Toolbear
9

Jika Anda ingin dependensi opsional sederhana seperti plugins, mis. Jika Anda menginstal foo Anda akan menjalankannya berwarna-warni tetapi jika tidak diinstal, Anda tidak memiliki masalah dan melihatnya dalam warna abu-abu, maka Anda dapat menggunakan dependensi dependen opsional dalam package.json :

{
  "name": "watchit",
  "version": "1.2.3",
  "optionalDependencies": {
    "foo": "^2.0.0"
  }
}

Dan dalam kode:

try {
  var foo = require('foo')
  var fooVersion = require('foo/package.json').version
} catch (er) {
  foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
  foo = null
}

// .. then later in your program ..

if (foo) {
  foo.doFooThings()
}

Diambil dari dokumentasi package.json .

PhoneixS
sumber
1

Apa yang saya lakukan adalah mengkonfigurasi skrip instalasi di package.json saya, di dalam scripts, seperti ini:

"install": "node ./my-tools/my-install.js",

Ini akan berjalan setelah npm installselesai. Saya menggunakannya sebagian besar untuk menghasilkan .envfile secara otomatis dengan default.

The my-install.jsScript bisa menjalankan perintah yang berbeda, membuat file, meminta input pengguna, jadi Anda bisa mengatakan "Ingin Redis atau Mongo?":

const exec = require('child_process').exec;
const readline = require('readline');

// Insert "Ask question script" here
// using readline core module

if ( option == 'mongo' )
  exec('npm install mongoose');

if ( option == 'redis' )
  exec('npm install redis');

Ini adalah jawaban yang sangat cepat, periksa readline untuk membaca input pengguna dengan benar dan proses anak untuk menjalankan perintah dan memproses output, dll.

Perhatikan juga bahwa skrip instal bisa apa saja yang Anda inginkan (python, bash, dll)

aesede
sumber
2
Meminta input pengguna akan mengacaukan build otomatis. Menjalankan npm installkembali di dalam skrip instal juga dapat memicu perilaku yang tidak diinginkan. Saya tidak merekomendasikan solusi ini.
Lambda Fairy
1

npm benar-benar tidak dirancang untuk ini, karena salah satu bagian tersulit dari manajemen dependensi adalah memastikan pembangunan yang cepat dan dapat direproduksi yang mudah dan relatif gagal. Tapi saya percaya ada use case, dan pasti ada untuk saya. Jadi saya menulis paket untuk melakukan persis apa yang Anda minta.

Paket saya adalah install-subset, dan dapat diinstal secara global dengannpm install -g install-subset

https://www.npmjs.com/package/install-sset

Pertama, Anda membuat daftar putih dan daftar hitam untuk subset instalasi bernama di package.json Anda seperti ini:

"subsets": {
    "build": {
        "whitelist": [
            "babel-cli",
            "dotenv"
        ]
    },
    "test": {
        "blacklist": [
            "eslint",
            "lint-rules",
            "prettier"
        ]
    }
}

Kemudian sebut dengan, misalnya, install-subset test

Ini untuk sementara akan menulis ulang package.json Anda agar tidak menginstal paket-paket tersebut dalam daftar hitam, kemudian mengembalikannya, yang tergantung pada paket-paketnya dapat menghemat banyak waktu dan bandwidth.

Juga bekerja dengan benang, bersifat open source dan masalah / PR disambut.

Dalam banyak kasus, saya menggunakan ini di server ci kami untuk menurunkan waktu pembuatan, dan pada proyek React Native terbaru kami, membuat pemasangan pengembang baru khas kami dari 72 detik menjadi sekitar 20 detik.

tabrindle
sumber