İçeriğe geç
academia.sh

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_modules dizininde aranır.
  • exports haritası 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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat