Node Projelerinin Manifest Dosyası
Her Node.js projesinin kök dizininde bir package.json dosyası bulunur. Sade bir JSON dosyasıdır ve projenizi tanımlar: adı, sürümü, hangi bağımlılıkları kullandığı, hangi komutları dışa açtığı... Kısacası npm ne zaman bir iş yapacak olsa önce bu dosyaya bakar. Silerseniz npm'in projeniz hakkında hiçbir fikri kalmaz.
Bu dosyayı oluşturmanın en hızlı yolu npm init komutudur:
npm init -y
-y bayrağı tüm soruları atlayıp varsayılan değerleri kabul eder. Sonuçta karşınıza şuna benzer bir dosya çıkar:
{
"name": "my-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
İşte iskeletin en sade hali. Bu alanların çoğu tek başına pek bir işe yaramaz — asıl değerlerini bağımlılıklar ve script'ler ekledikçe kazanıyorlar.
dependencies ve devDependencies farkı
İşin ağır yükünü neredeyse tamamen iki alan sırtlıyor: dependencies ve devDependencies. İkisi de paket adlarını sürüm aralıklarına eşleyen birer map yapısında.
Bu ayrımın tek bir önemli sebebi var: dependencies, kodunuzun çalışması için gerekli olan paketlerdir. devDependencies ise yalnızca geliştirme sırasında ihtiyaç duyduklarınızdır — test araçları, linter'lar, build araçları, tip kontrolcüleri. Birisi sizin paketinizi kendi projesine bağımlılık olarak kurduğunda, npm yalnızca dependencies altındakileri indirir; devDependencies atlanır.
Bu alanları npm otomatik olarak günceller. npm install express çalıştırdığınızda dependencies altına bir satır eklenir. npm install --save-dev vitest ise devDependencies altına bir satır ekler. Elle düzenlemeniz gereken durumlar çok nadirdir.
Sürüm aralıkları: ^, ~ ve sabit sürüm
^4.19.0 gibi gördüğünüz ifadeler aslında kesin sürümler değil, birer aralık. npm, semver kurallarına uyar ve sürümleri MAJOR.MINOR.PATCH şeklinde üçe ayırır:
- MAJOR artışları geriye dönük uyumluluğu bozar.
- MINOR artışları yeni özellikler ekler, ama mevcut olanı bozmaz.
- PATCH artışları hata düzeltmelerini içerir.
Her yerde karşınıza çıkacak iki operatör şunlar:
"express": "^4.19.0" // >= 4.19.0 ve < 5.0.0 (4.19.0 veya üstü herhangi bir 4.x.x)
"express": "~4.19.0" // >= 4.19.0 ve < 4.20.0 (4.19.0 veya üstü herhangi bir 4.19.x)
"express": "4.19.0" // tam olarak 4.19.0
^ npm'in paket kurarken varsayılan olarak kullandığı işaretçidir. Minor ve patch güncellemelerinin uyumlu kalacağına güvenir. ~ biraz daha temkinli — sadece patch güncellemelerine izin verir. Versiyonu işaretsiz yazarsanız, tam olarak o sürüme sabitlenir.
İşin can alıcı noktası şu: "az önce kurduğum sürüm" ile "aralığın izin verdiği sürüm" aynı şey değil. Bugün express@4.19.0 kurarsınız, bir ay sonra ekip arkadaşınız projeyi klonlayıp kurduğunda ^4.19.0 pekâlâ 4.19.5'e denk gelebilir. İşte tam bu noktada package-lock.json devreye girer — çözümlenen tam sürümleri kaydeder, böylece herkes birebir aynı bağımlılık ağacını alır. Bu dosyayı mutlaka repo'ya commit'leyin.
package.json scripts: Projenizin Komut Arayüzü
scripts alanı, sık kullandığınız komutlara kısayol tanımladığınız yerdir. Buraya eklediğiniz her şeyi npm run <isim> ile çalıştırabilirsiniz:
Script'ler hakkında bilmeniz gereken birkaç nokta:
npm start,npm testve birkaç özel adrunanahtar sözcüğüne ihtiyaç duymadan çalışır. Geri kalan her şey içinnpm run <ad>yazmanız gerekir.- Script'ler,
PATHdeğişkeninenode_modules/.bineklenmiş bir shell içinde çalışır. Bu sayede kurulu paketlerin binary dosyalarını doğrudan çağırabilirsiniz. Örneğinvitestglobal olarak kurulu olmasa bile"test": "vitest"sorunsuz çalışır. - Script'leri zincirleyebilirsiniz:
"build": "npm run lint && npm run compile". "Sırayla çalışsın, hata olursa dursun" demek için&&kullanın. pre<ad>vepost<ad>script'leri otomatik olarak tetiklenir. Meselaprebuildtanımlıysa,build'den önce kendiliğinden çalışır; ekstra bir ayar yapmanıza gerek yok.
Script'ler, projenizin komut arayüzüdür. İyi yazılmış bir package.json sayesinde projeye yeni katılan biri repoyu klonlayıp npm install çalıştırır, ardından wiki'ye bakmadan npm run dev veya npm test komutlarını doğrudan kullanabilir.
Giriş Noktaları: main, exports ve type
Bu alanlar, Node'a (ve bundler'lara) paketinizin nasıl yükleneceğini anlatır.
typealanı,.jsdosyalarının nasıl yorumlanacağını belirler."module"yazarsanız ESM (import/export) kullanılır. Hiç yazmazsanız veya"commonjs"derseniz CommonJS (require) devreye girer. Detaylar için CommonJS vs ESM dokümanına göz atın.main, eski usul giriş noktasıdır — yanirequire("my-lib")dediğinizde hangi dosyaya çözümleneceğini söyler. Eski araçlar hâlâ bunu dikkate alıyor.exportsise bunun modern ve daha katı halidir. Paketi kullananların tam olarak hangi dosyaları, hangi alt yol üzerinden import edebileceğini burada tanımlarsınız. Listede olmayan bir dosyayı import etmeye çalışırsanız hata alırsınız — bu bir bug değil, bilinçli bir tasarım. Public API'nizin kontrolü sizde.
Eğer paket yayınlamıyor, sadece bir uygulama geliştiriyorsanız bunların içinde sizi gerçekten ilgilendiren tek alan muhtemelen type olacaktır.
Gerçek hayattan bir package.json örneği
Hepsini bir araya getirdiğimizde, küçük bir Node uygulamasının package.json dosyası pratikte aşağı yukarı şöyle görünür:
engines.node alanına dikkat edin. Bu alan bilgi amaçlıdır — kullanıcının Node sürümü uyuşmuyorsa npm uyarı verir (engine-strict ile hata fırlatır). Yayınlayacağınız her paket için uygulamanız gereken iyi bir alışkanlık.
Bilmeye Değer Diğer Alanlar
Karşınıza çıkacak birkaç alan daha:
private: true— paketi yanlışlıkla npm'e yayınlamanızı engeller. Yayınlanmayacak her projeye eklemenizde fayda var.license—"MIT"veya"ISC"gibi SPDX tanımlayıcısı. Açık kaynak projelerde önemli.repository,bugs,homepage— npm registry sayfanızda görüntülenir.bin— paketiniz bir CLI sunuyorsa, komut adlarını burada script dosyalarıyla eşleyin. Kurulumdan sonra bu komutlar doğrudan çalıştırılabilir hale gelir.workspaces— monorepo'lar için; npm'e alt dizinleri birbirine bağlı paketler olarak ele almasını söyler.
Hepsine ihtiyacınız yok. Yaptığınız işe uygun olanlara ihtiyacınız var.
Sık Yapılan Hatalar
İnsanların tökezlediği birkaç nokta:
node_modulesklasörünü commit'lemek. Yapmayın..gitignoredosyasına ekleyin.package.jsonvepackage-lock.jsonikilisi, herhangi birininnpm installile klasörü yeniden oluşturması için yeterli.package-lock.jsondosyasını commit'lememek. Kesinlikle commit'leyin. Lockfile olmadan "benim makinemde çalışıyordu" senaryosu gerçeğe dönüşür; çünkü semver aralıkları zaman içinde farklı sürümlere çözümlenebilir.- Çalışma zamanı bağımlılıklarını
devDependenciesiçine koymak. Uygulamanız yerelde dev bağımlılıkları da yüklü olduğu için sorunsuz çalışabilir, ama production ortamında bunlar atlandığı için patlar. Yayınladığınız kod bir paketi kullanıyorsa, o paketdependenciesiçinde olmalı. - Sürümleri elle düzenleyip yeniden kurmamak.
package.jsoniçinde bir sürümü değiştirdiğinizdenpm installçalıştırın — yoksanode_modulesile lockfile senkron dışına çıkar.
Sırada: Node Çalışma Zamanı
package.json, Node'a projenizin ne olduğunu anlatır. Nasıl çalıştığına ise Node çalışma zamanı karar verir — modül çözümleme, yerleşik modüller, global değişkenler ve perde arkasındaki event loop. Bir sonraki sayfanın konusu tam olarak bu.
Sıkça Sorulan Sorular
package.json ne işe yarar?
Bir Node.js projesinin kimlik kartı gibidir. Projenin adını ve sürümünü, hangi paketlere bağımlı olduğunu, npm run ile çalıştırabileceğin script'leri ve giriş dosyası, modül tipi gibi üst bilgileri burada tutarsın. npm install komutu da neyi indireceğine bu dosyaya bakarak karar verir.
dependencies ile devDependencies arasındaki fark nedir?
dependencies, kodunun çalışma anında ihtiyaç duyduğu paketlerdir — express veya react gibi. devDependencies ise sadece geliştirme ya da build sırasında gereken şeylerdir: test araçları, bundler'lar, linter'lar. Biri senin paketini kendi projesine bağımlılık olarak kurduğunda, npm senin devDependencies listeni atlar.
package.json'daki ^ ve ~ işaretleri ne anlama geliyor?
Bunlar semver aralık operatörleridir. ^1.2.3, 1.2.3 ve üzeri tüm 1.x.x sürümlerine izin verir (major sürüm aynı kalır). ~1.2.3 daha katıdır — 1.2.3 ve üzeri 1.2.x sürümlerini kabul eder (minor aynı). Yalın bir 1.2.3 ise sürümü tam olarak sabitler. package-lock.json dosyası da çözümlenen kesin sürümleri kaydeder, böylece kurulumlar her makinede aynı sonucu verir.
package.json dosyasını nasıl oluştururum?
Boş bir klasörde npm init komutunu çalıştırıp soruları cevaplayabilirsin ya da npm init -y ile varsayılanları kabul edip dosyayı anında oluşturabilirsin. İstersen elle de yazabilirsin — sonuçta sadece bir JSON dosyası. Gerçekten zorunlu olan tek alanlar name ve version.