Ders 04 / 20
Modül Çözümleme
Üç tanımlayıcı türü, dosya uzantısı zorunluluğu, paket dizini arama zinciri, dışa aktarım haritası ve çözümlemenin programdan sorgulanması.
İçindekiler
Önceki ders sürecin dış dünyayla nasıl konuştuğunu kurdu. Bu dersin sorusu daha
dardır ama etkisi geniştir: import satırında yazan ad, hangi dosyaya karşılık gelir?
Yanıt üç ayrı kural kümesine dağılmıştır. Yazdığınız tanımlayıcının hangi kümeye girdiği ilk karakterinden anlaşılır ve seçim geri kalan her şeyi belirler.
Üç Tanımlayıcı Türü
Yerleşik tanımlayıcı, node: önekiyle başlar: node:fs, node:path,
node:http. Çalışma zamanının içine gömülü modülleri gösterir; dosya sisteminde
aranmaz.
Dosya tanımlayıcısı, ./, ../ veya bir kök yol ile başlar. İçinde bulunduğu
dosyanın konumuna göre çözülür.
Paket tanımlayıcısı, bu iki biçime de uymayan addır: olcum-araclari,
olcum-araclari/birim. Paket dizinlerinde aranır.
Üçü de tek bir dosyada yan yana kullanılabilir. Aşağıdaki düzen kurs boyunca tekrarlanacak bir yapıdır: bir paket bildirimi, bir yerel modül ve bağımlılık dizinindeki bir paket.
cozumleme/
package.json
ana.js
ozet.js
node_modules/
olcum-araclari/
package.json
index.js
birim.js
ic.js
// cozumleme/package.json { "name": "olcum-toplayici", "version": "1.0.0", "type": "module" }
// cozumleme/node_modules/olcum-araclari/package.json { "name": "olcum-araclari", "version": "1.0.0", "type": "module", "exports": { ".": "./index.js", "./birim": "./birim.js" } }
// cozumleme/node_modules/olcum-araclari/index.js export const ad = 'olcum-araclari';
// cozumleme/node_modules/olcum-araclari/birim.js export const birimler = { sicaklik: 'C', nem: '%' };
// cozumleme/node_modules/olcum-araclari/ic.js export const gizli = true;
// cozumleme/ozet.js export function ortalama(sayilar) { return sayilar.reduce((t, s) => t + s, 0) / sayilar.length; }
// cozumleme/ana.js import { readFileSync } from 'node:fs'; import { ortalama } from './ozet.js'; import { ad } from 'olcum-araclari'; import { birimler } from 'olcum-araclari/birim'; console.log('yerleşik modül :', typeof readFileSync); console.log('dosya modülü :', ortalama([21.4, 19.8, 24.1]).toFixed(2)); console.log('paket modülü :', ad); console.log('paket alt yolu :', birimler.sicaklik);
node cozumleme/ana.js
yerleşik modül : function dosya modülü : 21.77 paket modülü : olcum-araclari paket alt yolu : C
Dört dosyanın uzantısı .js; ES modülü olarak yorumlanmalarını sağlayan, en yakın
paket bildirimindeki "type": "module" alanıdır. Bağımlılık dizinindeki paketin
kendi bildirimi de aynı alanı taşır — bir paketin modül biçimi kendi bildiriminden
gelir, onu kullananın bildiriminden değil.
Dosya Tanımlayıcısında Uzantı Zorunludur
CommonJS’te require('./ozet') yazmak yeterliydi; çalışma zamanı sırayla
./ozet.js, ./ozet.json, ./ozet.node adlarını dener, bulamazsa ./ozet/
dizinindeki dizin dosyasına bakardı. Bu tahmin, her içe aktarımda birkaç dosya
sistemi çağrısı demektir ve aynı ad için farklı ortamlarda farklı dosya
seçilebilmesi anlamına gelir.
ES modüllerinde tahmin yoktur:
cd cozumleme && node -e "import('./ozet').catch(e => console.log(e.code))"
ERR_MODULE_NOT_FOUND
Uzantı yazmak bir külfet değil, çözümlemeyi tek adıma indiren bir sözleşmedir: bir tanımlayıcı tek bir adrese karşılık gelir ve karşılık, dosya sistemine bakmadan hesaplanabilir.
Paket Arama Zinciri
Paket tanımlayıcısı görüldüğünde, içe aktaran dosyanın bulunduğu dizinden başlanır ve
her adımda node_modules alt dizinine bakılır. Bulunamazsa bir üst dizine çıkılır;
kök dizine kadar sürer.
// cozumleme/derin/daha-derin/derin.js import { ad } from 'olcum-araclari'; console.log('ust dizindeki node_modules bulundu:', ad);
node cozumleme/derin/daha-derin/derin.js
ust dizindeki node_modules bulundu: olcum-araclari
Dosya iki dizin derindedir ve yanında bağımlılık dizini yoktur; ad, zincir yukarı tırmanılarak bulunmuştur. Bu kural, Modüller, Araçlar ve Ekosistem kursunda anlatılan bağımlılık ağacı yerleşiminin dayanağıdır: aynı paketin farklı sürümleri, farklı derinliklerdeki dizinlere yerleştirilerek bir arada bulunabilir.
Dışa Aktarım Haritası
Bir paketin exports alanı, dışarıdan hangi yolların içe aktarılabileceğini belirler.
Yukarıdaki paket iki giriş tanımlıyor: kök (.) ve ./birim. Üçüncü dosya haritada
yer almıyor:
cd cozumleme && node -e "import('olcum-araclari/ic.js').catch(e => console.log(e.code))"
ERR_PACKAGE_PATH_NOT_EXPORTED
Bu, dosyanın var olmamasından farklı bir hatadır: dosya yerinde duruyor, ama paket onu genel arayüzünün parçası saymıyor. Harita, paket yazarına Programlama Temelleri kursunda tanıtılan arayüz–gerçekleştirim ayrımını uygulama olanağı verir. Harita olmadığında paketin bütün dosyaları dışarıya açıktır ve içeride yapılan her yeniden düzenleme kullanıcıları kırabilir.
Bir paket kendi içinde de takma ad tanımlayabilir. imports alanındaki, # ile
başlayan adlar yalnızca o paketin kendi dosyalarından çözülür; dışarıdan
görünmezler. Bu düzenek Paket Yayımlama dersinde yeniden ele alınacak.
Çözümlemeyi Sorgulamak
Hangi tanımlayıcının hangi dosyaya karşılık geldiği programdan sorulabilir:
// cozumleme/coz.js const yollar = ['node:fs', './ozet.js', 'olcum-araclari', 'olcum-araclari/birim']; for (const yol of yollar) { const cozulen = import.meta.resolve(yol); console.log(yol.padEnd(22), cozulen.replace(/^.*\/cozumleme\//, './')); }
node cozumleme/coz.js
node:fs node:fs ./ozet.js ./ozet.js olcum-araclari ./node_modules/olcum-araclari/index.js olcum-araclari/birim ./node_modules/olcum-araclari/birim.js
Çıktıdaki yollar dosya adresleridir; örnekte okunabilirlik için ortak önek
kırpılmıştır, gerçek değerler file:// ile başlar. Yerleşik modül ise adresle değil,
kendi tanımlayıcısıyla döner — dosya sisteminde karşılığı olmadığı için.
Bu sorgulama, bir bağımlılığın beklenen dosyadan mı geldiğini doğrulamanın en kısa
yoludur. import.meta.resolve yalnızca ES modüllerinde bulunur; CommonJS tarafında
karşılığı require.resolve çağrısıdır.
İki biçim arasında köprü kurmak gerektiğinde, node:module modülündeki
createRequire fonksiyonu bir ES modülünün içinde çalışan bir require üretir. Bu, ES
modülü olarak yayımlanmamış bir bağımlılığı kullanmanın yoludur ve Paket Yayımlama
dersinde kullanılacaktır.
Modüller Bir Kez Değerlendirilir
Bir modül, çözümlenen adresi başına bir kez değerlendirilir; aynı adres birden çok yerden içe aktarılsa da gövdesi yeniden çalışmaz ve aynı dışa aktarım nesnesi paylaşılır. Bu, modül düzeyinde tutulan durumun süreç boyunca tek olduğu anlamına gelir — bir sayaç, bir bağlantı havuzu veya bir yapılandırma nesnesi modül gövdesinde oluşturulduğunda, onu içe aktaran herkes aynı örneği görür.
Ayrıntı şurada: teklik, tanımlayıcıya değil çözümlenen adrese bağlıdır. Aynı paketin iki farklı dizinde bulunan iki kopyası iki ayrı adres verir ve iki ayrı örnek üretir. Bağımlılık ağacında yinelenen sürümlerin ortaya çıkardığı sorunun kökeni budur.
import bildirimi yalnızca modülün en üst düzeyinde ve koşulsuz yazılabilir; çünkü
bağımlılıklar gövde çalışmadan önce çözülür. Koşula bağlı yükleme gerektiğinde, bir
söz döndüren import() fonksiyon biçimi kullanılır. Ölçüm toplayıcı bu biçimi, yalnızca
istendiğinde yüklenen çıktı biçimlendiricileri için kullanabilir.
Özet
- Tanımlayıcılar üç türdür:
node:önekli yerleşikler,./veya../ile başlayan dosya yolları ve bunların dışındaki paket adları. Tür, çözümleme kuralını belirler. - ES modüllerinde dosya uzantısı zorunludur; uzantı tahmini ve dizin dosyası araması CommonJS’e özgüdür.
- Paket adı, içe aktaran dosyanın dizininden başlayarak yukarı doğru her düzeydeki
node_modulesdizininde aranır. exportsharitası paketin genel arayüzünü sabitler; haritada olmayan bir dosyaya erişim, dosya var olsa bile reddedilir.- Modül, çözümlenen adres başına bir kez değerlendirilir; modül düzeyindeki durum o adresi paylaşan herkes için tektir.
Sonraki Adım
Çalışma zamanı modelinin dört parçası tamamlandı: barındıran ortam, olay döngüsü, süreç nesnesi ve modül çözümleme. Bundan sonraki konu, bu model üzerine kurulmuş yerleşik modülleri sırayla ele alır. İlk durak dosya sistemidir: aynı okuma işini sunan üç ayrı arayüz vardır ve aralarındaki seçim, olay döngüsü dersinde ölçülen engelleme bedelini doğrudan belirler.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.