Eklentiler için npm'de neden akran bağımlılıkları kullanılır?


218

Örneğin, bir Grunt eklentisi neden homurdanmaya bağımlılığını " akran bağımlılıkları " olarak tanımlar ?

Eklenti neden Grunt'u grunt-plug / node_modules'e kendi bağımlılığı olarak alamıyor ?

Akran bağımlılıkları burada açıklanmaktadır: https://nodejs.org/en/blog/npm/peer-dependencies/

Ama gerçekten anlamıyorum.

Misal

Şu anda yerel bir cihazda sunulacak bir / dist / klasörüne kaynak dosyalarımı oluşturmak için Grunt görevlerini kullanan AppGyver Steroids ile çalışıyorum. Ben npm ve grunt oldukça yeniyim, bu yüzden neler olup bittiğini tam olarak anlamak istiyorum.

Şimdiye kadar bunu alıyorum:

[rootfolder] /package.json , npm'ye grunt-steroidsgeliştirme için npm paketine bağlı olduğunu söyler :

  "devDependencies": {
    "grunt-steroids": "0.x"
  },

Tamam. [Rootfolder] 'da npm kurulumunu çalıştırmak bağımlılığı algılar ve [rootfolder] / node_modules / grunt-steroid'lerine homurdanma steroidleri kurar .

Npm sonra kendi bağımlılıklarını yükleyebilir böylece [rootfolder] /node_modules/grunt-steroids/package.json okur . grunt-steroids:

"devDependencies": {
    "grunt-contrib-nodeunit": "0.3.0",
    "grunt": "0.4.4"
  },
"dependencies": {
    "wrench": "1.5.4",
    "chalk": "0.3.0",
    "xml2js": "0.4.1",
    "lodash": "2.4.1"
  },
"peerDependencies": {
    "grunt": "0.4.4",
    "grunt-contrib-copy": "0.5.0",
    "grunt-contrib-clean": "0.5.0",
    "grunt-contrib-concat": "0.4.0",
    "grunt-contrib-coffee": "0.10.1",
    "grunt-contrib-sass": "0.7.3",
    "grunt-extend-config": "0.9.2"
  },

" Bağımlılıklar " paketleri benim için mantıklı olan [rootfolder] / node_modules / grunt-steroids / node_modules içine kurulur .

" DevDependencies " yüklü değil, eminim sadece kullanmaya çalışıyorum grunt-steroidsve üzerinde geliştirmek değil npm tespit tarafından kontrol edilir .

Ama sonra " peerDependencies " var.

Bunlar [rootfolder] / node_modules içine kuruludur ve [rootfolder] / node_modules / grunt-steroids / node_modules içinde neden bulunmadığını ve diğer homurdanma eklentileriyle (ya da her neyse) çatışmaların önlenmesini neden anlamıyorum ?

Yanıtlar:


421

TL; DR: [1] peerDependencies , açıkta olmayan "özel" bağımlılıkların aksine, tüketen koda maruz kalan (ve kullanması beklenen) bağımlılıklar içindir ve yalnızca bir uygulama ayrıntısıdır.

Eş akran bağımlılıklarının çözdüğü problem

NPM'nin modül sistemi hiyerarşiktir. Daha basit senaryolar için büyük bir avantaj, bir npm paketi yüklediğinizde, bu paketin kendi bağımlılıklarını beraberinde getirmesi ve böylece kutudan çıkmasıdır.

Ancak sorunlar şu durumlarda ortaya çıkar:

  • Hem projeniz hem de kullandığınız bazı modüller başka bir modüle bağlıdır.
  • Üç modül birbiriyle konuşmak zorundadır.

Örnek olarak

Diyelim ki bina YourCoolProjectyapıyorsunuz JacksModule 1.0ve ikisini de kullanıyorsunuz ve JillsModule 2.0. Diyelim ki bunun JacksModuleda bağlı olduğunu JillsModule, ancak farklı bir versiyona, diyelim 1.0. Bu 2 sürüm karşılanmadığı sürece sorun yoktur. Yüzeyin altında JacksModulekullanılması gerçeği JillsModulesadece bir uygulama detayıdır. JillsModuleİki kez paketliyoruz , ancak kutudan istikrarlı yazılım aldığımızda ödemek için küçük bir fiyat.

Ama şimdi ya bir JacksModuleşekilde bağımlılığını ortaya çıkarırsa JillsModule. Örneğin bir örneğini kabul eder JillsClass... Kütüphanenin kullanım new JillsClasssürümünü oluşturup 2.0ona ilettiğimizde ne olur jacksFunction? Bütün cehennem gevşeyecek! Basit şeyler gibi jillsObject instanceof JillsClassaniden dönecektir falseçünkü jillsObjectaslında bir örneğidir başka JillsClass , 2.0versiyonu.

Akran bağımlılıkları bunu nasıl çözer?

Npm söylüyorlar

Bu pakete ihtiyacım var, ancak modülün bazı özel sürümlerine değil, projenin bir parçası olan sürüme ihtiyacım var.

Npm, paketinizin bu bağımlılığa sahip olmayan veya uyumsuz bir sürümü olan bir projeye yüklendiğini gördüğünde , yükleme işlemi sırasında kullanıcıyı uyarır.

Akran bağımlılıklarını ne zaman kullanmalısınız?

  • Diğer projeler tarafından kullanılacak bir kütüphane oluştururken ve
  • Bu kütüphane başka bir kütüphane kullanıyor ve
  • Kullanıcının diğer kütüphaneyle de çalışmasını beklersiniz / ihtiyacınız var

Genel senaryolar, daha büyük çerçeveler için eklentilerdir. Gulp, Grunt, Babel, Mocha, vs. gibi şeyleri düşünün. Bir Gulp eklentisi yazarsanız, bu eklentinin, Gulp'in kendi özel sürümünüzle değil, kullanıcının projesinin kullandığı aynı Gulp ile çalışmasını istersiniz.


Açıklamalar

  1. Çok uzun; okumadım. Çok uzun sayılan bir metnin kısa bir özetini belirtmek için kullanılır.

2
Fark ettiğim ve hiçbir yerde söylenmediğim önemli bir şey, bir eklenti oluştururken, akran bağımlılıkları için iki paket bağımlılığımız olmalı mı? OP örnekte, görebilirsiniz "grunt": "0.4.4"devDependencies ve peerDependencies hem olduğunu ve bunun Buna ihtiyacım olduğunu hem gelir, çünkü orada yinelenen bir örneği bana mantıklı mı gruntdeğil aynı zamanda o, benim kendi kullanımı için paket kullanıcıları benim peerDependencies sürüm kilidine saygı duyduğu sürece kütüphane kendi sürümlerini kullanabilir. Bu doğru mu? Yoksa OP örneği çok kötü mü?
Vadorequest

4
Grunt hayranları olan bir Grunt eklentisi yaratan insanları hayal edebiliyorum :) Gibi eklentilerinin yapım süreci için Grunt kendilerini kullanmak için doğal görünüyor .... Ama neden eklentilerini çalışır Grunt sürüm aralığı kilitlemek istesin oluşturmak için kullandıkları inşa süreci ile? Bir dev bağımlılığı olarak eklemek, bunların ayrılmasını sağlar. Temel olarak 2 aşama vardır: inşa süresi ve çalışma süresi. Geliştirme süreleri boyunca geliştirme bağımlılıkları gereklidir. Çalışma zamanında düzenli ve akran bağımlılıkları gerekir. Tabii ki bağımlılık bağımlılıkları ile her şey hızlı kafa karıştırıcı hale geliyor :)
Stijn de Witt

1
Bu cevap için teşekkürler! Sadece eğer, sizin örnekte, netleştirmek için JacksModulebağlıdır JillsModule ^1.0.0ile JillsModulebir akran bağımlılığı olmak JacksModuleve YourCoolProjectkullanıyorlardı JacksModuleve JillsModule ^2.0.0biz yüklemek için bize bildirecektir NPM tarafından akran bağımlılık uyarı alacak, JillsModule ^1.0.0hem de. Peki o zaman ne olacak? YourCoolProjectşimdi JillsModuleyoluyla iki ithal sürümü olacak import jillsModule from "..."? Ve kullandığımda JacksModuleonu bir örneği geçmem gerektiğini nasıl hatırlarım JillsModule v1.0.0?
tonix

1
@tonix Aslında, sürüm uyumsuzluğunuz olması bir sorun olacaktır. peerDependencies bunu çözmez. Ancak sorunun açıklığa kavuşturulmasına yardımcı olur. Çünkü iki sürümü sessizce kullanmak yerine sürüm uyumsuzluğunu açıkça gösterecektir. Kitaplıkları seçen uygulama geliştiricisinin bir çözüm bulması gerekir.
Stijn de Witt

2
@tonix Veya üçüncü seçenek: repoyu klonlayın JacksModule, bağımlı olacak şekilde yükseltin JillsModule ^2.0.0ve proje sorumlusuna bir PR sunun. Bu bağımlılığın eski olduğunu ve güncellemenize yardımcı olmak istediğinizi söyleyen bir hata göndermeniz yardımcı olabilir. İyi bir PR yaparsanız, çoğu kütüphane sahibi bunu birleştirir ve bunun için teşekkür eder. Koruyucular yanıt vermiyorsa, çatalınızı adınız altında NPM adlarında yayınlayabilir ve bunun yerine çatalınızı kullanabilirsiniz. Herhangi bir şekilde, çözümler var ama peerDependencieskendi başına çözmüyor.
Stijn de Witt

26

Önce makaleyi tekrar okumanızı tavsiye ederim. Biraz kafa karıştırıcı ama Winston-mail ile olan örnek size bunun cevabını gösteriyor:

Örneğin, bu gibi yapalım winston-mail@0.2.3belirtilen "winston": "0.5.x"onun içinde "dependencies"o karşı test edilmiştir son sürümü çünkü nesne. Bir uygulama geliştiricisi olarak, en son ve en harika şeyleri istersiniz, böylece en son sürümlerini arar winstonve winston-mailpaketinize koyarsınız.

{
  "dependencies": {  
    "winston": "0.6.2",  
    "winston-mail": "0.2.3"  
  }  
}

Ancak şimdi, npm install komutunun çalıştırılması,

├── winston@0.6.2  
└─┬ winston-mail@0.2.3                
  └── winston@0.5.11

Bu durumda, bazı sorunlara neden olacak bir paketin birden fazla sürümüne sahip olmak mümkündür. Eş bağımlılıkları, npm geliştiricilerinin kullanıcının belirli bir modüle (kök klasöründe) sahip olduğundan emin olmasını sağlar. Ancak, bir paketin belirli bir sürümünü tanımlamanın, diğer sürümleri kullanan diğer paketlerle ilgili sorunlara yol açacağı noktasında haklısınız. Makalelerin belirttiği gibi, bu sorun npm geliştiricileriyle ilgilidir.

Tek bir tavsiye : düzenli bağımlılıklardan farklı olarak, akran bağımlılığı gereklilikleri yumuşak olmalıdır . Eş bağımlılıklarınızı belirli yama sürümlerine kilitlememelisiniz.

Bu nedenle geliştiriciler peerDependencies tanımlamak için semver takip etmelidir. GitHub'daki grunt-steroid paketi için bir sorun açmalısınız ...


1
Bunu söyledin, multiple versions of a package which would cause some issuesama bir paket yöneticisinin amacı bu değil mi? Hatta projede aynı paketin 2 versiyonunun bulunduğu aynı makalede daha fazla tartışıyorlar: biri geliştirici tarafından sağlanan ve diğeri 3. taraf kitaplığı tarafından sağlanan.
Adam Beck

1
Akran bağımlılığı noktasını anlıyorum ama winstonörnekte şimdi sadece winston-mailkütüphaneyi kullanamıyorum, çünkü versiyonum akran bağımlılığına uymuyor mu? Hiç kullanamayacağımdan, 1 kütüphane için en son ve en büyük geçici sürüme sahip olmayı tercih ederim.
Adam Beck

1
ilk yorumunuz için, anladığım ve kullandığım kadarıyla, testle ilgili olmalı, örneğin belirli bir 3. taraf paketi için tarafınızdan test edilmiş bir paketiniz varsa, paketinizin çalışacağı bağımlılık değişikliğiniz (hata düzeltmesi, ana özellik güncellemesi). Bu nedenle, belirli bir eklenti sürümü belirtebilirsiniz ve testlerinizle kaydedebilirsiniz.
Fer için

1
İkinci yorumunuzda: bu nedenle dokümanlarda geliştiricilerin paket bağımlılıklarına karşı yumuşak olmaları ve semver kullanmaları gerektiğini söylüyorlar, örneğin "0.2.1" yerine "~ 0.2.1" -> "0.2.x" "0.3.x" veya "> = 0.2.1" -> "0.2.x" ile "1.x" veya "x.2" arasındaki her şey değil. .. (ancak bir npm paketi için gerçekten tercih edilmez ~
Fer To

15

peerDependencies mümkün olan en basit örnekle açıkladı:

{
  "name": "myPackage",
  "dependencies": {
    "foo": "^4.0.0",
    "react": "^15.0.0"
  }
}


{
  "name": "foo"
  "peerDependencies": {
    "react": "^16.0.0"
  }
}

myPackage'da npm install çalıştırıldığında, React sürümünü ^15.0.0VE fooyalnızca React ile uyumlu olan yüklemeye çalıştığı için bir hata gönderilir ^16.0.0.

peerDependencies yüklü DEĞİLDİR.


Neden sadece tepki 16'yı foo'nun içinde dep olarak koymuyorsun? bu şekilde hem 15 hem de 16 kullanılabilir ve foo 16 ve mypackage 15 kullanabilir mi?
nitinsh99

React, hem React 15 hem de React 16'nın aynı sayfada bulunabilmesi için çalışma zamanında önyükleme yapılan bir çerçevedir ve her ikisinin de aynı anda güçlendirilmesi gerekir, bu da son kullanıcı için son derece ağır ve sorunlu olur. Eğer fooher ikisi ile çalışır 15 Tepki ve 16 tepki o zaman olabilir olarak peerDependency listelemek >=15 < 17.
Jens Bodal

cevabım nitinsh99 peerDependencies'ın amacını mümkün olan en basit örnekle açıklamaktı, peerDependencies tarafından atılan hatadan nasıl kurtulacağımızı değil
Christopher Tokar

@ nitinsh99 paket bağımlılığına tepki eklemek Hooks - Bir pakette çoklu tepki gibi bir sorun sağlayacaktır
Masood
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.