Apa perbedaan antara dependensi, dependensi devD, dan dependensi peerDdalam file npm package.json?

2030

Dokumentasi ini menjawab pertanyaan saya dengan sangat buruk. Saya tidak mengerti penjelasan itu. Adakah yang bisa mengatakannya dengan kata-kata yang lebih sederhana? Mungkin dengan contoh jika sulit untuk memilih kata-kata sederhana?

EDIT juga menambahkan peerDependencies, yang terkait erat dan dapat menyebabkan kebingungan.

Vitalii Korsakov
sumber
48
Perhatikan ada juga optionalDependenciessekarang.
Aidan Feldman
118
@AidanFeldman "optionalDependencies" adalah oxymoron saya saat itu
Nick Bull
1
Dokumentasi npm mengatakan: "dependensi": Paket yang dibutuhkan oleh aplikasi Anda dalam produksi. "devDependencies": Paket yang hanya diperlukan untuk pengembangan dan pengujian lokal. lihat tautan: docs.npmjs.com/...
Deke

Jawaban:

2367

Ringkasan perbedaan perilaku penting:

  • dependencies diinstal pada keduanya:

    • npm install dari direktori yang berisi package.json
    • npm install $package di direktori lain mana pun
  • devDependencies adalah:

    • juga diinstal pada npm installpada direktori yang berisi package.json, kecuali jika Anda melewati --productionbendera (lanjutkan jawaban Gayan Charith ).
    • tidak diinstal pada npm install "$package"direktori lain mana pun, kecuali jika Anda memberinya --devpilihan.
    • tidak diinstal secara transitif.
  • peerDependencies:

    • sebelum 3.0: selalu diinstal jika hilang, dan menimbulkan kesalahan jika beberapa versi dependensi yang tidak kompatibel akan digunakan oleh dependensi berbeda.
    • diharapkan mulai pada 3.0 (belum diuji): beri peringatan jika tidak ada npm install, dan Anda harus menyelesaikan sendiri ketergantungan secara manual. Saat berjalan, jika ketergantungan tidak ada, Anda mendapatkan kesalahan (disebutkan oleh @nextgentech )
  • Transitivitas (disebutkan oleh Ben Hutchison ):

    • dependencies dipasang secara transitif: jika A membutuhkan B, dan B membutuhkan C, maka C akan diinstal, jika tidak, B tidak dapat bekerja, dan begitu pula A.

    • devDependenciestidak diinstal secara transitif. Misalnya kita tidak perlu menguji B untuk menguji A, sehingga ketergantungan pengujian B dapat diabaikan.

Opsi terkait tidak dibahas di sini:

ketergantungan

dependenciesdiperlukan untuk menjalankan, devDependencieshanya untuk mengembangkan, misalnya: tes unit, Transkrip CoffeeScript ke JavaScript, minifikasi, ...

Jika Anda ingin mengembangkan sebuah paket, Anda mengunduhnya (mis. Via git clone), pergi ke root-nya yang berisi package.json, dan jalankan:

npm install

Karena Anda memiliki sumber aktual, jelas bahwa Anda ingin mengembangkannya, jadi secara default, keduanya dependencies(karena Anda harus, tentu saja, jalankan untuk mengembangkan) dan devDependencydependensi juga diinstal.

Namun, jika Anda hanya pengguna akhir yang hanya ingin menginstal paket untuk menggunakannya, Anda dapat melakukannya dari direktori mana saja:

npm install "$package"

Dalam hal ini, Anda biasanya tidak ingin dependensi pembangunan, sehingga Anda hanya mendapatkan apa yang dibutuhkan untuk menggunakan paket: dependencies.

Jika Anda benar-benar ingin menginstal paket pengembangan dalam kasus itu, Anda dapat mengatur devopsi konfigurasi true, mungkin dari baris perintah sebagai:

npm install "$package" --dev

Opsi ini falsesecara default karena ini adalah kasus yang jauh lebih jarang.

dependensi sebaya

(Diuji sebelum 3.0)

Sumber: https://nodejs.org/en/blog/npm/peer-dependencies/

Dengan dependensi reguler, Anda dapat memiliki beberapa versi dependensi: itu hanya diinstal di node_modulesdalam dependensi.

Misalnya jika dependency1dan dependency2keduanya bergantung pada dependency3versi yang berbeda, pohon proyek akan terlihat seperti:

root/node_modules/
                 |
                 +- dependency1/node_modules/
                 |                          |
                 |                          +- dependency3 v1.0/
                 |
                 |
                 +- dependency2/node_modules/
                                            |
                                            +- dependency3 v2.0/

Plugin, bagaimanapun, adalah paket yang biasanya tidak memerlukan paket lain, yang disebut host dalam konteks ini. Sebagai gantinya:

  • plugin diperlukan oleh tuan rumah
  • plugins menawarkan antarmuka standar yang tuan rumah harapkan temukan
  • hanya host yang akan dipanggil langsung oleh pengguna, jadi harus ada satu versi.

Misalkan jika dependency1dan dependency2rekan bergantung pada dependency3, pohon proyek akan terlihat seperti:

root/node_modules/
                 |
                 +- dependency1/
                 |
                 +- dependency2/
                 |
                 +- dependency3 v1.0/

Ini terjadi meskipun Anda tidak pernah menyebutkan dependency3dalam package.jsonfile Anda .

Saya pikir ini adalah contoh dari pola desain Inversion of Control .

Contoh prototipikal dari dependensi rekan adalah Grunt, host, dan plugin-nya.

Misalnya, pada plugin Grunt seperti https://github.com/gruntjs/grunt-contrib-uglify , Anda akan melihat bahwa:

  • grunt adalah peer-dependency
  • satu-satunya di require('grunt')bawah tests/: itu tidak benar-benar digunakan oleh program.

Kemudian, ketika pengguna akan menggunakan plugin, ia secara implisit akan memerlukan plugin dari Gruntfiledengan menambahkan grunt.loadNpmTasks('grunt-contrib-uglify')baris, tetapi gruntpengguna akan langsung menelepon.

Ini tidak akan berfungsi jika masing-masing plugin memerlukan versi Grunt yang berbeda.

Manual

Saya pikir dokumentasi menjawab pertanyaan dengan cukup baik, mungkin Anda tidak cukup akrab dengan node / manajer paket lainnya. Saya mungkin hanya memahaminya karena saya tahu sedikit tentang Ruby bundler.

Kuncinya adalah:

Hal-hal ini akan diinstal ketika melakukan npm link atau menginstal npm dari root paket dan dapat dikelola seperti parameter konfigurasi npm lainnya. Lihat npm-config (7) untuk informasi lebih lanjut tentang topik ini.

Dan kemudian di bawah npm-config (7) temukan dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
5
Ah. Saya melihat saya telah salah paham. Jawaban Anda berbunyi seolah-olah npm install packageadalah perintah yang akan Anda gunakan untuk menginstal semua paket yang bukan dependensi dev, daripada apa yang sekarang saya pikir Anda maksudkan, yaitu 'instal paket yang disebut [paket]', yang menurut saya itu berhasil sebelum membaca ini. Jika saya jadi Anda, saya akan mengedit untuk mengatakan [nama-paket] yang dengan jelas menunjukkan bahwa yang Anda maksud adalah 'masukkan-nama-di sini'.
Tom W
184
Ini bagus! Saya tidak pernah menyadari, tetapi jawaban ini telah mengajarkan saya bahwa perbedaan dependensi vs devDependensi hanya berlaku jika Anda akan menerbitkan paket npm. Jika Anda hanya mengerjakan aplikasi atau situs, itu tidak terlalu menjadi masalah. Terima kasih!
jedd.ahyoung
3
Posting ini harus diperbarui untuk mencerminkan peerDependenciesperilaku yang berubah di npm @ 3 mendatang. Dari blog.npmjs.org/post/110924823920/npm-weekly-5 : "Kami tidak akan lagi secara otomatis mengunduh dependensi peer. Sebaliknya, kami akan memperingatkan Anda jika dependensi peer belum diinstal. Ini mengharuskan Anda untuk menyelesaikan sendiri konflik peerDependency, secara manual, tetapi dalam jangka panjang hal ini akan membuat kecil kemungkinan Anda akan berakhir di tempat yang sulit dengan dependensi paket Anda. "
nextgentech
8
Juga, devDependencies tidak diinstal secara transitif oleh paket dependen. Contoh: paket A tergantung pada paket B. Paket B tergantung pada paket C, dan B juga bergantung pada paket D. Jika Anda menjalankan npm installdari paket A, Anda akan mendapatkan B dan C tetapi tidak D.
Ben Hutchison
9
Sangat penting untuk berkomentar yang devDependenciestidak diinstal ketika NODE_ENVdiatur ke production.
Augusto Franzoia
491

Jika Anda tidak ingin menginstal devDependencies, Anda dapat menggunakan npm install --production

Gayan Charith
sumber
1
npm install --save untuk ketergantungan perangkat lunak?
Vamsi Pavan Mahesh
19
npm install akan menginstal semua dependensi. --Simpan flag digunakan ketika Anda ingin menambahkan modul spesifik ke package.json juga. mis: - npm install uglify - save akan menginstal uglify di folder proyek Anda dan tambahkan uglify ke project, file package.json.
Gayan Charith
6
Dan karena kita berbicara tentang devDependencies, Anda dapat menggunakan --save-dev untuk menyimpan modul baru sebagai devDependency. Contoh: npm install uglify --save-dev
Mykaelos
9
Pada npm 5, --saveopsi tidak lagi diperlukan. Jika Anda melakukan "npm install my-package", itu akan menambahkan paket saya sebagai ketergantungan pada package.jsonfile Anda .
Martin Carel
hanya npm instal
sultan aslam
116

Sebagai contoh, moka biasanya merupakan devDependensi, karena pengujian tidak diperlukan dalam produksi, sedangkan ekspres adalah dependensi.

Dan Kohn
sumber
4
Saya akan condong ke arah menempatkan pengujian sebagai ketergantungan karena Anda mungkin ingin menjalankan tes mandiri sebelum meluncurkan server produksi
47
Sebagai gantinya saya akan merekomendasikan menggunakan layanan integrasi berkelanjutan seperti Hudson atau CircleCI yang menjalankan tes Anda dan kemudian menyebar ke produksi jika mereka lulus.
Dan Kohn
1
Mungkin masih relevan untuk menguji server yang sebenarnya karena server CI mungkin berbeda dari server prod, dan perbedaan ini misalnya mencegah aplikasi untuk memulai ...
Nicole
2
@ Nicole mengapa Anda membuat server staging Anda tidak identik dalam konfigurasi untuk prod Anda?
Lucas
1
Kemudian lagi, menambahkan dependensi tes sebagai dependensi reguler memperkenalkan sejumlah perpustakaan tambahan, yang masing-masing mungkin gagal dalam beberapa cara. Saya akan bersandar (pun!) Ke server produksi ringan dengan kode sesedikit mungkin pada mereka. Ingat, kode terbaik adalah tanpa kode!
Stijn de Witt
69

dependencies
Dependensi yang harus dijalankan oleh proyek Anda, seperti perpustakaan yang menyediakan fungsi yang Anda panggil dari kode Anda.
Mereka diinstal secara transitif (jika A tergantung pada B tergantung pada C, npm instal pada A akan menginstal B dan C).
Contoh: lodash: proyek Anda memanggil beberapa fungsi lodash.

devDependencies
Ketergantungan yang Anda hanya perlu selama pengembangan atau rilis, seperti kompiler yang mengambil kode Anda dan mengompilasinya menjadi javascript, kerangka kerja pengujian atau generator dokumentasi.
Mereka tidak diinstal secara transitif (jika A tergantung pada B dev-tergantung pada C, npm instal pada A akan menginstal B saja).
Contoh: grunt: proyek Anda menggunakan grunt untuk membangunnya sendiri.

peerDependencies
Ketergantungan yang terkait dengan proyek Anda, atau dimodifikasi, dalam proyek induk, biasanya merupakan plugin untuk beberapa pustaka atau alat lain. Ini hanya dimaksudkan sebagai pemeriksaan, memastikan bahwa proyek induk (proyek yang akan tergantung pada proyek Anda) memiliki ketergantungan pada proyek yang Anda kaitkan. Jadi jika Anda membuat plugin C yang menambahkan fungsionalitas ke perpustakaan B, maka seseorang yang membuat proyek A perlu memiliki ketergantungan pada B jika mereka memiliki ketergantungan pada C.
Mereka tidak diinstal (kecuali npm <3), mereka hanya diperiksa.
Contoh: grunt: proyek Anda menambahkan fungsionalitas ke grunt dan hanya dapat digunakan pada proyek yang menggunakan grunt.

Dokumentasi ini menjelaskan dependensi rekan dengan sangat baik: https://nodejs.org/en/blog/npm/peer-dependencies/

Juga, dokumentasi npm telah diperbaiki dari waktu ke waktu, dan sekarang memiliki penjelasan yang lebih baik dari berbagai jenis dependensi: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependencies

qwertzguy
sumber
63

Untuk menyimpan paket ke package.json sebagai dependensi dev:

npm install "$package" --save-dev

Ketika Anda menjalankannya npm installakan menginstal keduanya devDependenciesdan dependencies. Untuk menghindari instalasi devDependenciesjalankan:

npm install --production
Mohammed Safeer
sumber
3
Anda juga dapat menggunakan: npm i -S
Maysara Alhindi
36

Ada beberapa modul dan paket yang hanya diperlukan untuk pengembangan, yang tidak diperlukan dalam produksi. Seperti dikatakan di dokumentasi :

Jika seseorang berencana mengunduh dan menggunakan modul Anda dalam program mereka, maka mereka mungkin tidak ingin atau perlu mengunduh dan membuat kerangka uji atau dokumentasi eksternal yang Anda gunakan. Dalam hal ini, yang terbaik adalah membuat daftar item tambahan ini dalam hash dependensi devD.

Amberlamps
sumber
Bagaimana jika Anda hanya menjalankan file bundle.js saat produksi? apakah Anda benar-benar membutuhkan dependensi itu?
RegarBoy
Jika Anda menjalankan bundle.js di server, Anda melakukan webpack sisi-server atau sesuatu ... Silakan periksa apakah itu masalahnya karena biasanya tidak dan itu benar-benar membutuhkan banyak pekerjaan untuk menjalankannya dengan benar (saya tahu karena saya melakukan itu). Saya menduga bundle.js Anda hanya dilayani hingga peramban dan berisi kode sisi klien.
Stijn de Witt
16

Penjelasan sederhana yang membuatnya lebih jelas bagi saya adalah:

Saat Anda menggunakan aplikasi Anda, modul dalam dependensi perlu diinstal atau aplikasi Anda tidak akan berfungsi. Modul di devDependencies tidak perlu diinstal pada server produksi karena Anda tidak mengembangkan pada mesin itu. tautan

Jyoti Duhan
sumber
2
Jadi, jika kita membuat situs web dan dalam versi prod semua lib akan dimasukkan ke dalam vendor.js, semua deps kita harus menjadi dep dep jika kode yang dikompilasi dimasukkan ke dalam repo? Dan itu harus dilakukan, karena hal lain yang aneh adalah Anda harus mengkompilasi modul, tidak hanya menginstalnya (dan pengujian juga di suatu tempat di sini karena setiap perubahan dalam submodul dapat menyebabkan regresi) ...
Qwertiy
Jawaban yang luar biasa, tetapi ada pertanyaan? Apakah mungkin Webpack membuat bundel yang rusak? Dugaan saya adalah paket devDependencies tidak akan berfungsi dalam versi produk, webpack -pmaksud saya. tolong jawab pertanyaan saya.
AmerllicA
Jika ada masalah saat membangun produksi, proses penyebaran Anda harus dirancang sedemikian rupa sehingga menunjukkan kesalahan pada waktu pembuatan dan tidak mendorong kode yang rusak ke produksi (misalnya, Anda dapat mencoba Jenkins). Devdependensi tidak harus diinstal pada server produksi.
Jyoti Duhan
dan bagaimana dengan ketergantungan teman sebaya?
dev27
13

Saya ingin menambahkan jawaban pandangan saya tentang penjelasan dependensi ini

  • dependencies digunakan untuk penggunaan langsung dalam basis kode Anda, hal-hal yang biasanya berakhir pada kode produksi, atau potongan kode
  • devDependencies digunakan untuk proses pembuatan, alat yang membantu Anda mengelola bagaimana kode akhir akan berakhir, modul uji pihak ketiga, (mis. barang-barang webpack)
Sîrbu Nicolae-Cezar
sumber
Bagaimana dengan aset css?
Brian Zelip
8

Pendeknya

  1. Ketergantungan - npm install <package> --save-prodmenginstal paket yang diperlukan oleh aplikasi Anda di lingkungan produksi.

  2. DevDependencies - npm install <package> --save-devmenginstal paket yang hanya diperlukan untuk pengembangan dan pengujian lokal

  3. Cukup ketikkan npm installinstal semua paket yang disebutkan di package.json

jadi jika Anda bekerja pada komputer lokal Anda cukup ketik npm installdan lanjutkan :)

cherankrish
sumber
6

peerDependenciestidak masuk akal bagi saya sampai saya membaca cuplikan ini dari sebuah posting blog tentang topik yang disebutkan Ciro di atas :

Yang dibutuhkan [ plugins ] adalah cara mengekspresikan "dependensi" antara plugins dan paket host mereka. Beberapa cara mengatakan, "Saya hanya bekerja ketika dicolokkan ke versi 1.2.x paket host saya, jadi jika Anda menginstal saya, pastikan itu bersama dengan host yang kompatibel." Kami menyebut hubungan ini ketergantungan teman sebaya.

Plugin mengharapkan versi host tertentu ...

peerDependenciesadalah untuk plugin, pustaka yang membutuhkan pustaka "host" untuk menjalankan fungsinya, tetapi mungkin telah ditulis pada suatu waktu sebelum versi terakhir dari host dirilis.

Artinya, jika saya menulis PluginX v1untuk HostLibraryX v3dan pergi, tidak ada jaminan PluginX v1akan bekerja ketika HostLibraryX v4(atau bahkan HostLibraryX v3.0.1) dirilis.

... tetapi plugin tidak bergantung pada host ...

Dari sudut pandang plugin, itu hanya menambah fungsi ke pustaka host. Saya tidak benar-benar "perlu" host untuk menambahkan dependensi ke plugin, dan plugin sering tidak benar-benar bergantung pada host mereka. Jika Anda tidak memiliki host, plugin tersebut tidak melakukan apa-apa.

Ini berarti dependenciessebenarnya bukan konsep yang tepat untuk plugin.

Lebih buruk lagi, jika host saya diperlakukan seperti ketergantungan, kami akan berakhir dalam situasi ini yang disebutkan oleh posting blog yang sama (diedit sedikit untuk menggunakan host & plugin yang dibuat jawaban ini):

Tapi sekarang, [jika kita memperlakukan versi kontemporer HostLibraryX sebagai ketergantungan untuk PluginX,] menjalankan npm installhasil dalam grafik ketergantungan tak terduga dari

├── HostLibraryX@4.0.0
└─┬ PluginX@1.0.0
  └── HostLibraryX@3.0.0

Saya akan meninggalkan kegagalan halus yang berasal dari plugin menggunakan API [HostLibraryX] yang berbeda dari aplikasi utama ke imajinasi Anda.

... dan tuan rumahnya jelas tidak bergantung pada plugin ...

... itulah inti dari plugin. Sekarang jika tuan rumah cukup baik untuk memasukkan informasi dependensi untuk semua pluginnya, itu akan menyelesaikan masalah, tetapi itu juga akan memperkenalkan masalah budaya baru yang sangat besar : manajemen plugin!

Inti dari plugin adalah mereka dapat berpasangan secara anonim. Di dunia yang sempurna, memiliki tuan rumah mengelola mereka semua akan rapi & rapi, tapi kami tidak akan membutuhkan perpustakaan kucing kawanan.

Jika kita tidak bergantung secara hierarkis, mungkin kita adalah teman sebaya yang saling bergantung ...

Sebagai gantinya, kami memiliki konsep menjadi teman sebaya. Baik host maupun plugin tidak berada di bucket ketergantungan yang lain. Keduanya hidup pada tingkat yang sama dari grafik ketergantungan.


... tapi ini bukan hubungan yang dapat diautomasi. <<< Moneyball !!!

Jika saya PluginX v1dan mengharapkan rekan (yaitu, memiliki ketergantungan peer ) HostLibraryX v3, saya akan mengatakannya. Jika Anda telah memutakhirkan secara otomatis ke yang terbaru HostLibraryX v4(perhatikan itu versi 4 ) DAN telah Plugin v1diinstal, Anda perlu tahu, bukan?

npm tidak dapat mengelola situasi ini untuk saya -

"Hei, aku tahu kamu menggunakan PluginX v1! Aku secara otomatis menurunkan HostLibraryXdari v4 ke v3, kk?"

... atau...

"Hei, aku tahu kamu menggunakan PluginX v1. Itu mengharapkan HostLibraryX v3, yang kamu tinggalkan di debu selama pembaruan terakhir kamu. Untuk amannya, aku secara otomatis mencopot pemasangan Plugin v1!! 1!

Bagaimana kalau tidak, npm ?!

Jadi npm tidak. Ini memberi tahu Anda tentang situasinya, dan memungkinkan Anda mengetahui apakah HostLibraryX v4rekan yang cocok untuk itu Plugin v1.


Coda

peerDependencyManajemen yang baik dalam plugin akan membuat konsep ini bekerja lebih intuitif dalam praktiknya. Dari posting blog , sekali lagi ...

Salah satu saran: persyaratan ketergantungan sebaya, tidak seperti yang untuk ketergantungan reguler, harus lunak. Anda tidak boleh mengunci dependensi rekan Anda ke versi tambalan tertentu. Akan sangat menjengkelkan jika satu plugin Chai bergantung pada Chai 1.4.1, sementara yang lain bergantung pada Chai 1.5.0, hanya karena penulisnya malas dan tidak menghabiskan waktu mencari tahu versi minimum Chai yang sebenarnya. cocok dengan.

ruffin
sumber
4

Dependensi vs dependensi dev

Dev dependensi adalah modul yang hanya diperlukan selama pengembangan sedangkan dependensi diperlukan saat runtime. Jika Anda menggunakan aplikasi Anda, dependensi harus diinstal, atau aplikasi Anda tidak akan berfungsi. Perpustakaan yang Anda panggil dari kode Anda yang memungkinkan program untuk dijalankan dapat dianggap sebagai dependensi.

Misalnya - Bereaksi, Bereaksi - dom

Modul dependensi dev tidak perlu diinstal di server produksi karena Anda tidak akan mengembangkan di mesin itu. Kompiler yang menyamarkan kode Anda ke javascript, kerangka kerja pengujian dan generator dokumen dapat dianggap sebagai dependensi dev karena hanya diperlukan selama pengembangan.

Misalnya- ESLint, Babel, webpack

@ FYI,

mod-a
  dev-dependents:
    - mod-b
  dependents:
    - mod-c

mod-d
  dev-dependents:
    - mod-e
  dependents:
    - mod-a

----

npm install mod-d

installed modules:
  - mod-d
  - mod-a
  - mod-c

----

checkout the mod-d code repository

npm install

installed modules:
  - mod-a
  - mod-c
  - mod-e

Jika Anda menerbitkan ke npm, maka penting bahwa Anda menggunakan flag yang benar untuk modul yang benar. Jika itu adalah sesuatu yang perlu difungsikan oleh modul npm Anda, maka gunakan flag "--save" untuk menyimpan modul sebagai dependensi. Jika itu adalah sesuatu yang modul Anda tidak perlu berfungsi tetapi diperlukan untuk pengujian, maka gunakan bendera "--save-dev".

# For dependent modules
npm install dependent-module --save

# For dev-dependent modules
npm install development-module --save-dev
Selva Ganapathi
sumber
1

Ketika mencoba mendistribusikan paket npm, Anda harus menghindari penggunaan dependencies. Alih-alih, Anda perlu mempertimbangkan untuk menambahkan peerDependenciesatau menghapusnya dependencies.

Melchia
sumber
1

Saya menemukan penjelasan sederhana.

Jawaban singkat:

dependensi "... adalah yang dibutuhkan proyek Anda untuk dapat bekerja dalam produksi."

devDependencies "... adalah yang Anda butuhkan selama pengembangan."

peerDependencies "jika Anda ingin membuat dan menerbitkan perpustakaan Anda sendiri sehingga dapat digunakan sebagai dependensi"

Lebih detail dalam posting ini: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

kebutuhan pengguna-bantuan
sumber