deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Duyurulmamış npm fork'ları react-comic-viewer 1.1.0'da kontrollü-state yeniden çalışmasını tetikledi

Bir React maintainer'ı, çizgi roman görüntüleyici bileşeninin duyurulmamış üç npm fork'unu keşfetti; farklar dört yıllık bir API boşluğunu ortaya çıkardı ve bu boşluk artık 1.1.0 sürümünde giderildi.

Duyurulmamış npm fork'ları react-comic-viewer 1.1.0'da kontrollü-state yeniden çalışmasını tetikledi

Bir maintainer, kendi paketinin sessiz üç fork'unu buldu

piro0919 takma adıyla dev.to'da yayımlanan bir yazıya göre, çizgi roman ve manga okumak için kullanılan küçük bir React bileşeni olan react-comic-viewer'ın geliştiricisi, yakın zamanda başkaları tarafından yayımlanan ve kendi çalışmasına neredeyse birebir kopya olan üç npm paketi keşfetti. Üçü de orijinal açıklamayı yeniden kullanmış, hatta repository alanlarını geliştiricinin kaynak deposuna geri yöneltmişti. Yazarların hiçbiri upstream'de hiçbir zaman bir issue ya da pull request açmamıştı; yani türev paketler, geliştirici kayıt defterine göz atarken tesadüfen karşılaşana kadar tamamen radarının dışında varlığını sürdürdü.

Fork öndeydi ve bir bug report gibi okunuyordu

Maintainer'ın yazdığına göre en eski fork, orijinal paket ilk kez yayımlandıktan yaklaşık üç ay sonra ortaya çıkmış ve neredeyse bir yıl boyunca güncellenmeye devam etmişti. Bir noktada sürüm numarası orijinalin oldukça önündeydi: 0.3.5'e karşı 0.6.3. Diff'i okurken, fork'un commit geçmişinin çoğu issue tracker'dan daha net bir hikâye anlattığını gördü: fork, build'den Sass'ı çıkarmış, bir className prop'u desteği eklemiş, hotkey yönetimi getirmiş ve bileşenin kontrollü kullanımını gösteren yeni bir örnek dosya içermişti.

Bu sorunlardan ikisi o zamandan beri upstream'de çözülmüştü; className boşluğu, fork'un çözmesinden yaklaşık bir yıl sonra giderildi. Üçüncüsü giderilmemişti. Dört yıl sonra bile bileşen hâlâ hiçbir kontrollü mod sunmuyordu.

Dört yıllık tasarım boşluğu

Fork'un örneği, bileşeni currentPage, isExpansion ve sayfa değişimi callback'leri gibi prop'larla yönetiyordu; gerçek paketin hiç sahip olmadığı bir API'yi bu. Upstream'de karşılık gelen prop'lar initialCurrentPage ve initialIsExpansion idi: çağıran taraf başlangıç sayfasını bir kez veriyor, bileşen de bu state'i ömrünün geri kalanında kendisi yönetiyordu.

Maintainer'ın açıkladığı gibi bu bir demo için sorun değil ama gerçek uygulamalar için yetersiz. Parent'ın sayfayı ayarlama yolu olmadığından okuyucu içindekiler tablosundan bir konuma atlayamıyor, geçerli sayfa URL ile senkron tutulamıyor ve önce satın alınması gereken bir bölümün sayfa geçişi yakalanamıyor. Bu özelliklerin her biri, parent bileşenin kontrolü elinde tutmasını gerektiriyor ve bu hiçbir zaman mümkün olmadı.

1.1.0 sürümü neleri değiştiriyor

1.1.0 sürümüyle gelen çözüm, standart controlled/uncontrolled desenini izliyor. Yeni bir useControllableState hook'u, çağıran taraf bir değer sağladığında baypas edilen dahili bir state tutuyor. İki uygulama detayı önem taşıyor: ref'ler, parent'lar satır içi arrow function geçse bile setter'ı stabil tutuyor; onChange çağrısı ise bir effect içinde değil setter'ın içinde yaşıyor, çünkü kontrollü modda yerel değer hiçbir zaman değişmiyor ve onu izleyen bir effect hiç tetiklenmezdi.

İki dahili davranış geçişi zorlaştırdı. Tam ekrana geçiş genişletilmiş görünümü zorunlu kılıyordu ve iki sayfalı yayılım'a geçmek geçerli sayfayı çift sayıya aşağı yuvarlıyordu. Kontrollü modda ikisi de artık onChange üzerinden geçiyor; yani parent isteği yok sayarsa hiçbir şey değişmiyor — yerel bir kontrollü input ile aynı semantik.

Sürüm, currentPage ve isExpansion'ı isteğe bağlı, birbirinden bağımsız prop'lar olarak ekliyor: birini sağlayın ve o size ait olur, ikisini de boş bırakın ve eski davranışa dokunulmaz. Ayrıca sayfa değişmeden önce tetiklenen onTryMoveNextPage ve onTryMovePrevPage ekleniyor; pages girdisinin, görüntüleyicinin kendi image elementine uygulayacağı class adını alan bir fonksiyon olmasına izin veriliyor, böylece çağıranlar lazy loading için kendi markup'larını koyabiliyor. Sürüme canlı bir demo da eşlik ediyor.

Hikâyenin ortaya koyduğu ekosistem sorunu

Tek bir bileşenin ötesinde bu olay, paket kayıt defterlerinin türev çalışmaları ne kadar kötü görünür kıldığını gösteriyor. Fork yazarları maintainer'a hiç temas etmediği için, yıllarca süren sinyal — gerçek sorunlara çalışan çözümler — orijinal yazarın varlığından haberdar olmadığı paketlerde çürüdü ve onları yalnızca tesadüfen buldu. Bileşen için npm'de arama yapan herkes bir fork'u aynı kolaylıkla kurabilirdi; çünkü kopyalar aynı açıklamayı ve repository URL'sini taşıyordu ve kod tabanlarının ayrıştığına dair hiçbir işaret yoktu. Kayıt defteri isimleri bağımsızca talep edildiğinden, birbirine neredeyse benzeyen paketler süresizce yan yana var olabilir; onları bağlayan hiçbir şey olmaz ve orijinal yayımcıya hiçbir bildirim ulaşmaz.

Neden önemli

Duyurulmamış fork'lar açık kaynak dünyasında iki ucu keskin. Maintainer'lar için alışılmadık derecede dürüst bug report'lardır: biri bir duvara çarpmış, sorunu düzgünce çözmüş ve sonucu yayımlamıştır; commit mesajları tam olarak neyin eksik olduğunu belgeler. Kullanıcılar için ise bir supply-chain tehlikesidir — benzer isimler, özdeş metadata, farklı kod ve hatların ayrıldığını kimseye bildiren bir kanal yok. Ekosistemler için bu hikâye, en az direnç gösteren yolun issue açmaktan fork'lamaktan geçtiğini ve fark etme yükünün orijinal isme sahip olana düştüğünün bir hatırlatmasıdır. Maintainer'ın kendi çıkarsaması, muhtemelen kendisinin de aynısını yapacağını söylediği fork yazarlarına yönelik bir suçlama değil, gecikmeye dair bir pişmanlık: keşke daha önce bakmış olsaydı.

  • #npm
  • #react
  • #open-source
  • #supply-chain
  • #javascript

İlgili yazılar